应用市场

03.服务器准备

1、将webSerser.apk 安装到手机
2、将WebInfos放入sdcard根目录

04.MyApplication初始化工作

1、清单文件注册
        android:name=".AppStoreApplication"
2、应用
public class AppStoreApplication extends Application {}
3、创建服务
<service android:name="myService" android:process=":remote"></service>
4、AppStoreApplication 的onCreate执行2次

列出所有进程:adb shell top

程序入口做什么?
package cn.nubia.nubiaappstore;

import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;

import cn.nubia.nubiaappstore.utils.LogUtils;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/4/27 19:24
 * version: 1.0
 * desc   : 清单文件注册
 * android:name=".AppStoreApplication"
 *
 * <service android:name="myService" android:process=":remote"></service>
 * onCreate执行多次
 */
public class AppStoreApplication extends Application {

    public static Context mContext;
    public static int mainThreadId;
    public static Handler mainHandler;

    public static AppStoreApplication mInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        LogUtils.e("gordon", "application onCreate:" + this);

        mInstance = this;
        //context
        mContext = getApplicationContext();
        //线程间通信
        mainHandler = new Handler();
        //判读当前是在主线程还是子线程
        mainThreadId = Process.myTid();

        new Thread(new Runnable() {
            @Override
            public void run() {
                //主线程的Looper
                Handler mainHandler1 = new Handler(Looper.getMainLooper());
                //子线程的Looper
                Handler subHandler = new Handler();
            }
        }).start();
    }
}

05.UiUtils工具类

package cn.nubia.nubiaappstore.utils;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Process;
import android.view.View;
import android.widget.Toast;

import cn.nubia.nubiaappstore.AppStoreApplication;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/4/27 20:05
 * version: 1.0
 * desc   : 处理和UI操作相关的工具类
 */
public class UiUtils {

    //获取全局context
    public static Context getApplicationContext() {
        return AppStoreApplication.mInstance.context;
    }

    //获取主线程的handler
    public static Handler getMainThreadHandler() {
        return AppStoreApplication.mInstance.mainHandler;
    }

    //获取主线程的线程id
    public static int getMainThreadId() {
        return AppStoreApplication.mInstance.mainThreadId;
    }

    //获取字符串
    public static String getString(int resId) {
        return getApplicationContext().getResources().getString(resId);
    }

    //获取字符串数组
    public static String[] getStringArray(int resId) {
        return getApplicationContext().getResources().getStringArray(resId);
    }

    //获取drawable
    public static Drawable getDrawable(int resId) {
        return getApplicationContext().getResources().getDrawable(resId);
    }

    //获取color
    public static int getColor(int resId) {
        return getApplicationContext().getResources().getColor(resId);
    }

    //
    public static int getDimen(int resId) {
        return getApplicationContext().getResources().getDimensionPixelSize(resId);
    }

    //dip2px
    public static int dip2px(int dip) {
        //屏幕密度
        float density = getApplicationContext().getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f);
    }

    //px2dip
    public static int px2dip(int dip) {
        //屏幕密度
        float density = getApplicationContext().getResources().getDisplayMetrics().density;
        return (int) (dip / density + 0.5f);
    }

    //加载布局文件
    public static View inflateView(int resId) {
        return View.inflate(getApplicationContext(), resId, null);
    }

    //展示toast
    public static void showToast(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    }

    //是否在主线程
    public static boolean isRunOnUiThread() {
        //1、获取当前线程id
        int curThreadId = Process.myTid();
        //2、获取主线程id
        int mainThreadId = getMainThreadId();
        //3、比较
        return curThreadId == mainThreadId;
    }

    /**
     * 保证r在主线程
     *
     * @param r 任务
     */
    public static void runOnUiThread(Runnable r) {
        if (isRunOnUiThread()) {//主线程
            r.run();
        } else {//子线程
            getMainThreadHandler().post(r);//将任务r丢到主线程的消息队列
        }
    }
}

06.布局文件&ViewPager设置数据

在这里插入代码片

08.显示ViewPager内容以及页签控件

创建fragment缓存
package cn.nubia.nubiaappstore.fragment;

import java.util.HashMap;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/4/27 21:26
 * version: 1.0
 * desc   : viewpager对fragment对象进行缓存
 */
public class FragmentFactory {

    private static HashMap<Integer, BaseFragment> sSavedFragment = new HashMap<>();

    public static BaseFragment getFragment(int position) {
        BaseFragment fragment = sSavedFragment.get(position);
        if (fragment == null) {
            switch (position) {
                case 0:
                    fragment = new HomeFragment();
                    break;
                case 1:
                    fragment = new AppFragment();
                    break;
                case 2:
                    fragment = new GameFragment();
                    break;
                case 3:
                    fragment = new SubjectFragment();
                    break;
                case 4:
                    fragment = new RecommendFragment();
                    break;
                case 5:
                    fragment = new CategoryFragment();
                    break;
                case 6:
                    fragment = new HotFragment();
                    break;
            }
            sSavedFragment.put(position, fragment);
        }
        return fragment;
    }
}
在adapter使用:
        @Override
        public Fragment getItem(int position) {
            BaseFragment fragment = FragmentFactory.getFragment(position);
            return fragment;
        }

页签控件:绑定viewpager
        mViewPager = findViewById(R.id.view_pager);
        mPagerTab = findViewById(R.id.pager_tab);
        mFm = getSupportFragmentManager();
        mViewPager.setAdapter(new MainPagerAdapter(mFm));
        //必须重新getPageTitle
        mPagerTab.setViewPager(mViewPager);

        /**
         * 必须重新,父类返回null
         * @param position
         * @return
         */
        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return mTabNames[position];
        }

09.LoadingPage的创建_添加相同View

package cn.nubia.nubiaappstore.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

import cn.nubia.nubiaappstore.R;
import cn.nubia.nubiaappstore.utils.UiUtils;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/4/27 21:55
 * version: 1.0
 * desc   : 载入framelayout,共同的布局等
 * LoadingPage作为每个Fragment所需要展示的view对象存在
 * 1、加载中的状态 STATE_LOADING mLoadingView
 * 2、加载失败 STATE_ERROR mErrorView
 * 3、加载成功,但数据集合数量为0 STATE_EMPTY mEmptyView
 * 4、加载成功 STATE_SUCCESS mSuccessView
 */
public class LoadingPage extends FrameLayout {

    private View mLoadingView;
    private View mErrorView;
    private View mEmptyView;
    private View mSuccessView;

    public LoadingPage(Context context) {
        this(context, null);
    }

    public LoadingPage(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public LoadingPage(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        if (mLoadingView == null) {
            mLoadingView = createLoadingView();
            addView(mLoadingView);//add 到帧布局中
        }
        if (mErrorView == null) {
            mErrorView = createErrorView();
            addView(mErrorView);//add 到帧布局中
        }
        if (mEmptyView == null) {
            mEmptyView = createEmptyView();
            addView(mEmptyView);//add 到帧布局中
        }
        if (mSuccessView == null) {
            mSuccessView = createSuccessView();
            addView(mSuccessView);//add 到帧布局中
        }
    }

    private View createSuccessView() {
        View view = UiUtils.inflateView(R.layout.layout_success);
        return view;
    }


    private View createEmptyView() {
        View view = UiUtils.inflateView(R.layout.layout_empty);
        return view;
    }

    private View createLoadingView() {
        View view = UiUtils.inflateView(R.layout.layout_loading);
        return view;
    }

    private View createErrorView() {
        View view = UiUtils.inflateView(R.layout.layout_error);
        return view;
    }
}

10.给LoadingPage增加状态

    //状态值
    public static final int STATE_LOADING = 0;
    public static final int STATE_ERROR = 1;
    public static final int STATE_EMPTY = 2;
    public static final int STATE_SUCCESS = 3;

    //当前状态
    private int mCurrState = STATE_LOADING;

    /**
     * 根据当前状态动态控制显示
     */
    private void showRightPage() {
/*        if (mCurrState == STATE_LOADING) {
            mLoadingView.setVisibility(View.VISIBLE);
            mErrorView.setVisibility(View.GONE);
            mEmptyView.setVisibility(View.GONE);
        } else if (mCurrState == STATE_ERROR) {
            mLoadingView.setVisibility(View.GONE);
            mErrorView.setVisibility(View.VISIBLE);
            mEmptyView.setVisibility(View.GONE);
        } else if (mCurrState == STATE_EMPTY) {
            mLoadingView.setVisibility(View.GONE);
            mErrorView.setVisibility(View.GONE);
            mEmptyView.setVisibility(View.VISIBLE);
        }*/
        mLoadingView.setVisibility((mCurrState == STATE_LOADING) ? View.VISIBLE : View.GONE);
        mErrorView.setVisibility((mCurrState == STATE_ERROR) ? View.VISIBLE : View.GONE);
        mEmptyView.setVisibility((mCurrState == STATE_EMPTY) ? View.VISIBLE : View.GONE);
    }

11.自定义ProgressBar效果

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!--一层又一层效果叠加-->
    <item>
        <rotate
            android:drawable="@drawable/spinner_big_inner"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="720"
            android:visible="true"></rotate>
    </item>

    <item>
        <rotate
            android:drawable="@drawable/spinner_big_outer"
            android:fromDegrees="360"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="0"
            android:visible="true"></rotate>
    </item>
</layer-list>

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateDrawable="@drawable/customer_progress" />

在这里插入图片描述
14.加载网络数据的实现

在这里插入代码片

在这里插入图片描述
16.枚举的讲解

    /**
     * 创建对象简化
     * 构造方法私有化,达到对象数量控制
     */
    public enum ResultState {

        LOADING(STATE_LOADING), ERROR(STATE_ERROR), EMPTY(STATE_EMPTY), SUCCESS(STATE_SUCCESS);

        public int state;

        private ResultState(int state) {
            this.state = state;
        }
    }

    //加载网络数据
     //mCurrState = onLoad();
     ResultState res = onLoad();
     if (res != null) {
         mCurrState = res.state;
     }

02.MyBaseAdapter抽取第一步

1、抽取基类:
package cn.nubia.nubiaappstore.adapter;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.ArrayList;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/5/1 14:38
 * version: 1.0
 * desc   : BaseAdapter抽取
 */
public class MyBaseAdapter extends BaseAdapter {

    private ArrayList<String> dataList;

    public MyBaseAdapter(ArrayList<String> dataList) {
        this.dataList = dataList;
    }

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}

2、继承
    private class MyAdapter extends MyBaseAdapter {

        public MyAdapter(ArrayList<String> dataList) {
            super(dataList);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = UiUtils.inflateView(R.layout.list_item_home);
                holder = new ViewHolder();
                holder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.tvContent.setText(mDataList.get(position));
            return convertView;
        }
    }

    static class ViewHolder {
        TextView tvContent;
    }

03.MyBaseAdapter抽取第二步_泛型的引入

package cn.nubia.nubiaappstore.adapter;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.ArrayList;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/5/1 14:38
 * version: 1.0
 * desc   : BaseAdapter抽取
 * 增加泛型
 * 封装的思想:
 *  抽取基类:
 *      在基类中做的一般都是通用的事情
 *      不通用的事情
 *          1、父类不知道如何完成的事情,通过抽象方法来交给子类实现
 *          2、父类不知道的数据类型,通过泛型来解决,泛型是自定义的一种不存在的类型,这种类型究竟是啥,在定义子类的时候确定
 *              尖括号的位置
 *                  如果在自己的类名后面,代表定义了一个泛型
 *                  如果跟在父类的名称后面,代表确定父类所定义的泛型类型
 *
 */
public class MyBaseAdapter<T> extends BaseAdapter {

    private ArrayList<T> dataList;

    public MyBaseAdapter(ArrayList<T> dataList) {
        this.dataList = dataList;
    }

    @Override
    public int getCount() {
        return dataList.size();
    }

    @Override
    public T getItem(int position) {
        return dataList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}

04.MyBaseAdapter抽取第三步_getView的抽取_BaseHolder的创建

高层次抽取

06.PullToRefreshListView的使用

github:推荐
https://github.com/chrisbanes/Android-PullToRefresh
https://github.com/chrisbanes/PhotoView

自定义属性、自定义控件

08.下拉刷新和上拉加载更多的实现

        PullToRefreshListView  mListView = new PullToRefreshListView (UiUtils.getApplicationContext());
        mListView.setMode(PullToRefreshBase.Mode.BOTH);//既有上拉加载,又有下拉刷新
        mListView.setAdapter(new MyAdapter(mDataList));

例子:
    @Override
    public View fragmentCreateSuccessView() {
        for (int i = 0; i < 20; i++) {
            mDataList.add("Home:" + i);
        }
        mListView = new PullToRefreshListView(UiUtils.getApplicationContext());
        mListView.setMode(PullToRefreshBase.Mode.BOTH);//既有上拉加载,又有下拉刷新
        mAdapter = new MyAdapter(mDataList);
        mListView.setAdapter(mAdapter);
        mListView.setOnRefreshListener(new RefreshListener());//回调
        return mListView;
    }

    private class RefreshListener implements PullToRefreshBase.OnRefreshListener<ListView> {
        @Override
        public void onRefresh(PullToRefreshBase<ListView> refreshView) {
            LogUtils.e("gordon", "update");
            if (mListView.getCurrentMode() == PullToRefreshBase.Mode.PULL_FROM_END) {
                //加载下一页数据
                loadMore();
            } else {
                //刷新数据
                requestData();
            }
        }
    }

    //加载下一页数据
    private void loadMore() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (int i = 0; i < 20; i++) {
                    mDataList.add("Home:" + i);
                }
                UiUtils.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                        mListView.onRefreshComplete();
                    }
                });
            }
        }).start();
    }

    //刷新数据
    private void requestData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mDataList.clear();
                for (int i = 0; i < 20; i++) {
                    mDataList.add("new home:" + i);
                }
                UiUtils.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                        mListView.onRefreshComplete();
                    }
                });
            }
        }).start();
    }

09.HttpHelper的引入

引入以下文件

在这里插入图片描述
10.BaseProtocol的建立

package cn.nubia.nubiaappstore.http.protocol;

import cn.nubia.nubiaappstore.http.HttpHelper;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/5/1 17:12
 * version: 1.0
 * desc   : 自定义http协议
 */
public abstract class BaseProtocol<T> {

    public T getData() {
        return getDataFromServer();
    }

    private T getDataFromServer() {
        //url组成 主域名+模块名
        String url = HttpHelper.URL + getKey() + getParams();
        HttpHelper.HttpResult httpResult = HttpHelper.get(url);
        if (httpResult!=null) {
            String json = httpResult.getString();
            return parseJson(json);
        }
        return null;
    }

    //解析数据
    protected abstract T parseJson(String json);

    //请求参数
    public abstract String getParams();

    //模块名
    public abstract String getKey();
}
子类:
package cn.nubia.nubiaappstore.http.protocol;

/**
 * author : gordon
 * e-mail : gordon_sun07@163.com
 * date   : 2019/5/1 17:27
 * version: 1.0
 * desc   :
 */
public class HomeProtocol extends BaseProtocol{
    @Override
    protected Object parseJson(String json) {
        return null;
    }

    @Override
    public String getParams() {
        return "?index=0";
    }

    @Override
    public String getKey() {
        return "home";
    }
}

11.okhttp3 请求

基本使用:
https://www.jianshu.com/p/da4a806e599b
P版本异常:
CLEARTEXT communication to 127.0.0.1 not permitted by network security policy
解决:
https://blog.youkuaiyun.com/qq_18620851/article/details/80617549

12.上拉加载下拉刷新更新数据内容

在这里插入代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值