自定义LoadingPage实现网络请求显示的四种情况的封装

来源:互联网 发布:划船机 知乎 编辑:程序博客网 时间:2024/06/05 09:15

我们在网络请求数据的时候,通常有四种情况:
1、正在加载
2、加载失败
3、加载成功,但是没有数据
4、加载成功,同时返回数据
这时候需要我们根据这四种情况显示不同的页面视图。
这里我们可以自定义一个LoadingPage类来实现这四种情况的切换。
一、新建一个LoadingPage类继承FrameLayout
1.定义4种不同的显示状态
state_loading=1;
state_error=2;
state_empty=3;
state_success=4;
state_current=1;

2.提供4种不同界面:
正在加载中
加载失败
加载成功,但是数据为空
加载成功,且有数据

3.根据state_current的值,决定显示哪个界面。(初始化时,应该显示:正在加载)

4.在类中,实现联网操作,根据联网的结果,修改state_current的值,决定显示哪个界面。

5.如果是state_current=4,需要考虑如何将数据传递给具体的Fragment.

LoadingPage.class

import android.content.Context;import android.support.annotation.AttrRes;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.text.TextUtils;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import android.widget.FrameLayout;import com.loopj.android.http.AsyncHttpClient;import com.loopj.android.http.AsyncHttpResponseHandler;import com.loopj.android.http.RequestParams;import com.willkong.p2pclient.R;import com.willkong.p2pclient.util.UIUtils;/** * 作者: willkong on 2017/11/8. * 作用:加载页四种情况:1、正在加载 2、加载失败 3、加载成功,但是没有数据 4、加载成功,同时返回数据 */public abstract class LoadingPage extends FrameLayout{    //1.定义4种不同的显示状态    private static final int STATE_LOADING=1;    private static final int STATE_ERROR=2;    private static final int STATE_EMPTY=3;    private static final int STATE_SUCCESS=4;    private static int state_current=STATE_LOADING;//默认情况下,当前状态为正在加载    //2.提供4种不同的界面    private View view_loading;    private View view_error;    private View view_empty;    private View view_success;    private LayoutParams params;    public LoadingPage(@NonNull Context context) {        this(context,null);    }    public LoadingPage(@NonNull Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public LoadingPage(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    //初始化方法    private void init() {        //实例化view        //1、提供布局显示的参数        params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);        if (view_loading==null){            //2、加载布局            view_loading = UIUtils.getView(R.layout.page_loading);            //3、添加到当前的Fragment中            addView(view_loading, params);        }        if (view_empty==null){            //2、加载布局            view_empty = UIUtils.getView(R.layout.page_empty);            //3、添加到当前的Fragment中            addView(view_empty, params);        }        if (view_error==null){            //2、加载布局            view_error = UIUtils.getView(R.layout.page_error);            //3、添加到当前的Fragment中            addView(view_error, params);        }        //3、根据state_current的值,决定显示哪个界面。(初始化时,应该显示:正在加载)        showSafePage();    }    //保证如下的操作在主线程中执行的,更新界面    private void showSafePage() {        UIUtils.runOnUiThread(new Runnable() {            @Override            public void run() {                //保证runnable中的操作在主线程中执行                showPage();            }        });    }    //更新界面    private void showPage() {        //根据state_current的值,决定显示哪个view        view_loading.setVisibility(state_current==STATE_LOADING?VISIBLE:INVISIBLE);        view_error.setVisibility(state_current==STATE_ERROR?VISIBLE:INVISIBLE);        view_empty.setVisibility(state_current==STATE_EMPTY?VISIBLE:INVISIBLE);        if (view_success==null){            view_success = UIUtils.getView(layoutId());            addView(view_success,params);        }        view_success.setVisibility(state_current==STATE_SUCCESS?VISIBLE:INVISIBLE);    }    public abstract int layoutId();    private ResultState resultState;    //在show()方法中实现联网加载数据    public void show(){        String url = url();        //不需要联网        if (TextUtils.isEmpty(url)){            resultState = ResultState.SUCCESS;            resultState.setContent("");            loadImage();            return;        }//4.在类中,实现联网操作,根据联网的结果,修改state_current的值,决定显示哪个界面。        AsyncHttpClient client = new AsyncHttpClient();        client.get(url(),params(),new AsyncHttpResponseHandler(){            @Override            public void onSuccess(String content) {                if (TextUtils.isEmpty(content)){                    resultState = ResultState.EMPTY;                    resultState.setContent("");                }else {                    resultState = ResultState.SUCCESS;                    resultState.setContent(content);                }                loadImage();            }            @Override            public void onFailure(Throwable error, String content) {                resultState = ResultState.ERROR;                resultState.setContent("");                loadImage();            }        });    }    private void loadImage() {        switch (resultState){            case ERROR:                state_current = STATE_ERROR;                break;            case EMPTY:                state_current = STATE_EMPTY;                break;            case SUCCESS:                state_current = STATE_SUCCESS;                break;        }        //根据修改以后的state_current,更新视图的显示。        showSafePage();        //5.如果是state_current=4,需要考虑如何将数据传递给具体的Fragment.如果联网成功了,把内容回调给界面        if (state_current==STATE_SUCCESS){            onSuccess(resultState,view_success);        }    }    protected abstract void onSuccess(ResultState resultState, View view_success);    //提供联网的请求地址    protected abstract String url();    //提供联网的请求参数    protected abstract RequestParams params();    //提供枚举类,封装联网后的状态值和数据    public enum ResultState{        ERROR(2),EMPTY(3),SUCCESS(4);        int state;        ResultState(int state){            this.state = state;        }        private String content;        public String getContent() {            return content;        }        public void setContent(String content) {            this.content = content;        }    }}

BaseFragment.class

import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import com.loopj.android.http.RequestParams;import com.willkong.p2pclient.ui.LoadingPage;import butterknife.ButterKnife;/** * 作者: willkong on 2017/11/3. * 作用:HomeFragment、InvestFragment、MeFragment、MoreFragment的基类 */public abstract class BaseFragment extends Fragment {    private LoadingPage loadingPage;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {        loadingPage = new LoadingPage(container.getContext()){            @Override            public int layoutId() {                return getLayoutId();            }            @Override            protected void onSuccess(ResultState resultState, View view_success) {                ButterKnife.bind(BaseFragment.this, view_success);                initTitle();                initData(resultState.getContent());            }            @Override            protected String url() {                return getUrl();            }            @Override            protected RequestParams params() {                return getParams();            }        };        return loadingPage;    }    //为了保证loadingPage不为null    @Override    public void onActivityCreated(@Nullable Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        show();    }    protected abstract RequestParams getParams();    protected abstract String getUrl();    //初始化界面的数据    protected abstract void initData(String content);    //初始化title    protected abstract void initTitle();    //提供一个创建方法,提供布局    public abstract int getLayoutId();    @Override    public void onDestroyView() {        super.onDestroyView();        ButterKnife.unbind(this);    }    //联网请求数据    public void show(){        loadingPage.show();    }}

MyApplication.class

import android.app.Application;import android.content.Context;import android.os.Handler;/** * 作者: willkong on 2017/10/31. * 作用:APP全局 */public class MyApplication extends Application{    //在整个应用执行过程中,需要提供的变量    public static Context context;//需要使用的上下文对象:application实例    public static Handler handler;//需要使用的handler    public static Thread mainThread;//提供主线程对象    public static int mainThreadId;//提供主线程对象的id    @Override    public void onCreate() {        super.onCreate();        context = this.getApplicationContext();        handler = new Handler();        mainThread = Thread.currentThread();//实例化当前Application的线程即为主线程        mainThreadId = android.os.Process.myTid();//获取当前线程的id        //设置未捕获异常的处理器//        CrashHandler.getInstance().init();    }}

UIUtils.class

import android.content.Context;import android.os.Handler;import android.support.v4.content.ContextCompat;import android.view.View;import android.widget.Toast;import com.willkong.p2pclient.common.MyApplication;/** * 作者: willkong on 2017/10/31. * 作用:专门提供为处理一些UI相关的问题而创建的工具类, *      提供资源获取的通用方法,避免每次都写重复的代码获取结果。 */public class UIUtils {    public static Context getContext(){        return MyApplication.context;    }    public static Handler getHandler(){        return MyApplication.handler;    }    //返回指定colorId对应的颜色值    public static int getColor(int colorId){        return ContextCompat.getColor(getContext(),colorId);    }    //加载指定viewId的视图对象,并返回    public static View getView(int viewId){        View view = View.inflate(getContext(), viewId, null);        return view;    }    public static String[] getStringArr(int strArrId){        String[] stringArray = getContext().getResources().getStringArray(strArrId);        return stringArray;    }    //将dp转化为px    public static int dp2px(int dp){        //获取手机密度        float density = getContext().getResources().getDisplayMetrics().density;        return (int) (dp * density + 0.5);//实现四舍五入    }    public static int px2dp(int px){        //获取手机密度        float density = getContext().getResources().getDisplayMetrics().density;        return (int) (px / density + 0.5);//实现四舍五入    }    //保证runnable中的操作在主线程中执行    public static void runOnUiThread(Runnable runnable) {        if(isInMainThread()){            runnable.run();        }else{            UIUtils.getHandler().post(runnable);        }    }    //判断当前线程是否是主线程    private static boolean isInMainThread() {        int currentThreadId = android.os.Process.myTid();        return MyApplication.mainThreadId == currentThreadId;    }    public static void toast(String message,boolean isLengthLong){        Toast.makeText(UIUtils.getContext(), message,isLengthLong? Toast.LENGTH_LONG : Toast.LENGTH_SHORT).show();    }}

Fragment中的调用如:HomeFragment.class

import android.content.Context;import android.text.TextUtils;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.loopj.android.http.RequestParams;import com.squareup.picasso.Picasso;import com.willkong.p2pclient.R;import com.willkong.p2pclient.bean.Image;import com.willkong.p2pclient.bean.Index;import com.willkong.p2pclient.bean.Product;import com.willkong.p2pclient.common.BaseFragment;import com.willkong.p2pclient.ui.RoundProgress;import com.youth.banner.Banner;import com.youth.banner.BannerConfig;import com.youth.banner.Transformer;import com.youth.banner.loader.ImageLoader;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import butterknife.Bind;/** * 作者: willkong on 2017/10/25. * 作用:首页 */public class HomeFragment extends BaseFragment {    @Bind(R.id.iv_title_back)    ImageView ivTitleBack;    @Bind(R.id.tv_title)    TextView tvTitle;    @Bind(R.id.iv_title_setting)    ImageView ivTitleSetting;    @Bind(R.id.banner)    Banner banner;    @Bind(R.id.tv_home_product)    TextView tvHomeProduct;    @Bind(R.id.tv_home_yearrate)    TextView tvHomeYearrate;    @Bind(R.id.roundPro_home)    RoundProgress roundProHome;    @Override    protected RequestParams getParams() {        return null;    }    @Override    protected String getUrl() {//        return AppNetConfig.INDEX;        return null;    }    private Index index;    private int currentProgress;    @Override    protected void initData(String content) {        index = new Index();        if (!TextUtils.isEmpty(content)){            //解析json数据            JSONObject jsonObject = JSON.parseObject(content);            //解析json对象数据            String proInfo = jsonObject.getString("proInfo");            Product product = JSON.parseObject(proInfo,Product.class);            //解析json数组数据            String imageArr = jsonObject.getString("imageArr");            List<Image> images = jsonObject.parseArray(imageArr, Image.class);            index.product = product;            index.images = images;            //更新页面数据            tvHomeProduct.setText(product.name);            tvHomeYearrate.setText(product.yearRate + "%");            //获取数据中的进度            currentProgress = Integer.parseInt(index.product.progress);            //在分线程中实现进度的动态变化//                new Thread(runnable).start();            roundProHome.runWithAnimation(100, currentProgress, 50);            //设置banner样式            banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR_TITLE);            //设置图片加载器            banner.setImageLoader(new GlideImageLoader());            //设置图片地址的构成集合            ArrayList<String> imgesUrl = new ArrayList<String>(index.images.size());            for (int i = 0; i < index.images.size(); i++) {                imgesUrl.add(index.images.get(i).IMAURL);            }            banner.setImages(imgesUrl);            //设置banner动画效果            banner.setBannerAnimation(Transformer.DepthPage);            //设置标题集合(当banner样式有显示title时)            String[] titles = new String[]{"分享砍学费", "人脉总动员", "想不到你是这样的app"};            banner.setBannerTitles(Arrays.asList(titles));            //设置自动轮播,默认为true            banner.isAutoPlay(true);            //设置轮播时间            banner.setDelayTime(1500);            //设置指示器位置(当banner模式中有指示器时)            banner.setIndicatorGravity(BannerConfig.CENTER);            //banner设置方法全部调用完毕时最后调用            banner.start();        }    }    @Override    protected void initTitle() {        ivTitleBack.setVisibility(View.GONE);        tvTitle.setText("首页");        ivTitleSetting.setVisibility(View.GONE);    }    @Override    public int getLayoutId() {        return R.layout.fragment_home;    }    class GlideImageLoader extends ImageLoader {        @Override        public void displayImage(Context context, Object path, ImageView imageView) {            /**             注意:             1.图片加载器由自己选择,这里不限制,只是提供几种使用方法             2.返回的图片路径为Object类型,由于不能确定你到底使用的那种图片加载器,传输的到的是什么格式,那么这种就使用Object接收和返回,你只需要强转成你传输的类型就行,切记不要胡乱强转!             */            //Picasso 加载图片简单用法            Picasso.with(context).load((String) path).into(imageView);        }    }}
原创粉丝点击