自定义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); } }}
阅读全文
0 0
- 自定义LoadingPage实现网络请求显示的四种情况的封装
- 自定义UI 网络 请求类的封装
- LoadingPage的抽取
- 网络请求的封装
- 封装的网络请求
- 网络请求的封装
- 网络请求的封装
- ios自定义异步post网络请求的封装
- 网络请求的封装方法
- 各种网络请求的封装
- HttpURLConnection网络请求的封装
- Xutils3网络请求的封装
- Xutils3网络请求的封装
- 封装OkHttp的网络请求
- okHttp封装,使用超简单的网络请求实现
- Retrofit+okhttp3的简单封装实现网络请求和拦截
- 简单实现RxJava2+Okhttp+Retrofit2的网络请求框架封装
- 常见的Android 网络请求的封装;
- LODOP打印控件实现设计并且代码生成
- Angular JS 之对表格进行操作
- MQTT协议简记
- Oracle:简单分析火车票余票查询和座位剩余
- Mangos源码分析(11):服务器公共组件实现之状态机
- 自定义LoadingPage实现网络请求显示的四种情况的封装
- 海思3516出现错误Returned error for crccheck of ino #441. Expect badness...
- VirtualBox5.1.16下对CentOS6.9系统扩展磁盘空间(扩容)
- 以太坊智能合约 Solidity 的常用数据类型介绍
- 各流派的大神和他们的故事
- xml文件的路径出现红色字体
- mysql数据库误删除后的数据恢复操作说明
- Mangos源码分析(12):服务器公共组件实现之事件与信号
- Spring CLI示例快速入门