根据网络请求结果返回加载失败、加载为空、加载成功、加载中的自定义视图
2017-06-11 00:00
399 查看
LoadingPage继承帧布局。
init方法中先把所有布局都一次加载进去;调用showpage方法来判断最后显示那一个页面。
ThreadManager.class线程池管理类
UiUtils.calss其实就是确定在主线程中更新UI操作。
BaseApplication.class记得要在清单文件配置
使用这个自定义布局,需要调用show()方法,才能显示。
ViewUtils.clss
在子类fragment中使用
圆角图片背景设置
背景图片选择器
上图框架主要是传智GooglePlay所用,此文只为记录,以便下次查阅。
源码下载
http://pan.baidu.com/s/1bpnJO2F
init方法中先把所有布局都一次加载进去;调用showpage方法来判断最后显示那一个页面。
public abstract class LoadingPage extends FrameLayout { public static final int STATE_UNKOWN = 0; public static final int STATE_LOADING = 1; public static final int STATE_ERROR = 2; public static final int STATE_EMPTY = 3; public static final int STATE_SUCCESS = 4; public int state = STATE_UNKOWN; private View loadingView;// 加载中的界面 private View errorView;// 错误界面 private View emptyView;// 空界面 private View successView;// 加载成功的界面 public LoadingPage(Context context) { super(context); init(); } public LoadingPage(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public LoadingPage(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { loadingView = createLoadingView(); // 创建了加载中的界面 if (loadingView != null) { this.addView(loadingView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } errorView = createErrorView(); // 加载错误界面 if (errorView != null) { this.addView(errorView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } emptyView = createEmptyView(); // 加载空的界面 if (emptyView != null) { this.addView(emptyView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } showPage();// 根据不同的状态显示不同的界面 } // 根据不同的状态显示不同的界面 private void showPage() { if (loadingView != null) { loadingView.setVisibility(state == STATE_UNKOWN || state == STATE_LOADING ? View.VISIBLE : View.INVISIBLE); } if (errorView != null) { errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE : View.INVISIBLE); } if (emptyView != null) { emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE : View.INVISIBLE); } if (state == STATE_SUCCESS) { if (successView == null) { successView = createSuccessView(); this.addView(successView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } successView.setVisibility(View.VISIBLE); } else { if (successView != null) { successView.setVisibility(View.INVISIBLE); } } } /* 创建了空的界面 */ private View createEmptyView() { View view = View.inflate(UiUtils.getContext(), R.layout.loadpage_empty, null); Button re_loading_page_bt = (Button) view.findViewById(R.id.re_loading_page_bt); re_loading_page_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { show(); } }); return view; } /* 创建了错误界面 */ private View createErrorView() { View view = View.inflate(UiUtils.getContext(), R.layout.loadpage_error, null); Button loading_page_bt = (Button) view.findViewById(R.id.loading_page_bt); loading_page_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //TODO 设置网络连接,也可以直接忽略在布局中设置网络按钮 } }); return view; } /* 创建加载中的界面 */ private View createLoadingView() { View view = View.inflate(UiUtils.getContext(), R.layout.loadpage_loading, null); return view; } public enum LoadResult { error(2), empty(3), success(4); int value; LoadResult(int value) { this.value = value; } public int getValue() { return value; } } // 根据服务器的数据 切换状态 public void show() { if (state == STATE_ERROR || state == STATE_EMPTY) { state = STATE_LOADING; } // 请求服务器 获取服务器上数据 进行判断 // 请求服务器 返回一个结果 ThreadManager.getInstance().createLongPool().execute(new Runnable() { @Override public void run() { SystemClock.sleep(500); final LoadResult result = load(); UiUtils.runOnUiThread(new Runnable() { @Override public void run() { if (result != null) { state = result.getValue(); showPage(); // 状态改变了,重新判断当前应该显示哪个界面 } } }); } }); showPage(); } /*** * 创建成功的界面 * * @return */ public abstract View createSuccessView(); /** * 请求服务器 * * @return */ protected abstract LoadResult load(); }
ThreadManager.class线程池管理类
public class ThreadManager { private ThreadManager() { } private static ThreadManager instance = new ThreadManager(); private ThreadPoolProxy longPool; private ThreadPoolProxy shortPool; public static ThreadManager getInstance() { return instance; } // 联网比较耗时 // cpu的核数*2+1 public synchronized ThreadPoolProxy createLongPool() { if (longPool == null) { longPool = new ThreadPoolProxy(5, 5, 5000L); } return longPool; } // 操作本地文件 public synchronized ThreadPoolProxy createShortPool() { if(shortPool==null){ shortPool = new ThreadPoolProxy(3, 3, 5000L); } return shortPool; } public class ThreadPoolProxy { private ThreadPoolExecutor pool; private int corePoolSize; private int maximumPoolSize; private long time; public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long time) { this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.time = time; } /** * 执行任务 * @param runnable */ public void execute(Runnable runnable) { if (pool == null) { // 创建线程池 /* * 1. 线程池里面管理多少个线程2. 如果排队满了, 额外的开的线程数3. 如果线程池没有要执行的任务 存活多久4. * 时间的单位 5 如果 线程池里管理的线程都已经用了,剩下的任务 临时存到LinkedBlockingQueue对象中 排队 */ pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, time, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(10)); } pool.execute(runnable); // 调用线程池 执行异步任务 } /** * 取消任务 * @param runnable */ public void cancel(Runnable runnable) { if (pool != null && !pool.isShutdown() && !pool.isTerminated()) { pool.remove(runnable); // 取消异步任务 } } } }
UiUtils.calss其实就是确定在主线程中更新UI操作。
public class UiUtils { /** * 获取到字符数组 * @param tabNames 字符数组的id */ public static String[] getStringArray(int tabNames) { return getResource().getStringArray(tabNames); } public static Resources getResource() { return getContext().getResources(); } public static Context getContext(){ return BaseApplication.getApplication(); } /** dip转换px */ public static int dip2px(int dip) { final float scale = getResource().getDisplayMetrics().density; return (int) (dip * scale + 0.5f); } /** px转换dip */ public static int px2dip(int px) { final float scale = getResource().getDisplayMetrics().density; return (int) (px / scale + 0.5f); } /** * 把Runnable 方法提交到主线程运行 * @param runnable */ public static void runOnUiThread(Runnable runnable) { // 在主线程运行 if(android.os.Process.myTid()== BaseApplication.getMainTid()){ runnable.run(); }else{ //获取handler BaseApplication.getHandler().post(runnable); } } public static View inflate(int id) { return View.inflate(getContext(), id, null); } public static Drawable getDrawalbe(int id) { return getResource().getDrawable(id); } public static int getDimens(int homePictureHeight) { return (int) getResource().getDimension(homePictureHeight); } /** * 延迟执行 任务 * @param run 任务 * @param time 延迟的时间 */ public static void postDelayed(Runnable run, int time) { BaseApplication.getHandler().postDelayed(run, time); // 调用Runable里面的run方法 } /** * 取消任务 * @param auToRunTask */ public static void cancel(Runnable auToRunTask) { BaseApplication.getHandler().removeCallbacks(auToRunTask); } /** * 可以打开activity * @param intent */ public static void startActivity(Intent intent) { // 如果不在activity里去打开activity 需要指定任务栈 需要设置标签 if(BaseActivity.activity==null){ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent); }else{ BaseActivity.activity.startActivity(intent); } } }
BaseApplication.class记得要在清单文件配置
public class BaseApplication extends Application { private static BaseApplication application; private static int mainTid; private static Handler handler; @Override // 在主线程运行的 public void onCreate() { super.onCreate(); application = this; mainTid = android.os.Process.myTid(); handler = new Handler(); } public static Context getApplication() { return application; } public static int getMainTid() { return mainTid; } public static Handler getHandler() { return handler; } }
使用这个自定义布局,需要调用show()方法,才能显示。
public abstract class BaseFragment extends Fragment { @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); show(); } private LoadingPage loadingPage; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (loadingPage == null) { // 之前的frameLayout 已经记录了一个爹了 爹是之前的ViewPager loadingPage = new LoadingPage(getActivity()){ @Override public View createSuccessView() { return BaseFragment.this.createSuccessView(); } @Override protected LoadResult load() { return BaseFragment.this.load(); } }; }else{ ViewUtils.removeParent(loadingPage);// 移除frameLayout之前的爹 } return loadingPage; // 拿到当前viewPager 添加这个framelayout } /*** * 创建成功的界面 * @return */ public abstract View createSuccessView(); /** * 请求服务器 * @return */ protected abstract LoadingPage.LoadResult load(); public void show(){ if(loadingPage!=null){ loadingPage.show(); } } /**校验数据 */ public LoadingPage.LoadResult checkData(List datas) { if(datas==null){ return LoadingPage.LoadResult.error;// 请求服务器失败 }else{ if(datas.size()==0){ return LoadingPage.LoadResult.empty; //数据为空 }else{ return LoadingPage.LoadResult.success;//请求数据成功 } } } }
ViewUtils.clss
public class ViewUtils { public static void removeParent(View v){ // 先找到爹 在通过爹去移除孩子 ViewParent parent = v.getParent(); //所有的控件 都有爹 爹一般情况下 就是ViewGoup if(parent instanceof ViewGroup){ ViewGroup group=(ViewGroup) parent; group.removeView(v); } } }
在子类fragment中使用
public class HomeFragment extends BaseFragment { @Override public View createSuccessView() { //如果有数据的话返回显示的页面 return null; } @Override protected LoadingPage.LoadResult load() { //网络请求返回数据 List datas=new ArrayList(); //最后data为网络数据或者网络状态 return checkData(datas); //return LoadingPage.LoadResult.empty; } }
圆角图片背景设置
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="10dp"></corners> <padding android:bottom="10dp" android:top="10dp"></padding> <solid android:color="@color/colorAccent"></solid> </shape>
背景图片选择器
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/btn_shape_pressed" /> <item android:state_pressed="false" android:drawable="@drawable/btn_shape" /> </selector>
上图框架主要是传智GooglePlay所用,此文只为记录,以便下次查阅。
源码下载
http://pan.baidu.com/s/1bpnJO2F
相关文章推荐
- MVC扩展ActionInvoker,自定义ActionInvoker,根据请求数据返回不同视图
- WebClient网络请求的Referer头导致请求结果失败
- 从网络中下载文件,并且写入SDCARD根目录下,成功返回true,失败返回false
- 【iOS开发】SDWebImage框架,加载图片,失败之后,居然直接跳过不再去请求网络数据了?
- 加载网络图片所显示的转圈效果及加载成功前与失败后所显示的图标
- 自定义View 01 --网络请求返回数据为空时的提示界面
- 关于HttpUrlConnection网络请求之返回结果的中文乱码原因的探索
- AlertDialog对话框自定义大小,加载网络请求,点击不消失
- android界面之美---自定义网络请求进度加载对话框
- 完美解决Android的WebView加载失败(404,500),显示的自定义视图
- 完美解决Android的WebView加载失败(404,500),显示的自定义视图
- 自定义带网络请求的UITableView中tableHeaderView视图
- SDWebImage 加载网络图片失败,重新运行,就能加载成功。
- 自定义网络加载视图NetworkImageView
- 安卓学习笔记---完美解决Android的WebView加载失败(404,500),显示的自定义视图
- 如何让 Spring MVC Controller 的同一个 URL 请求,根据逻辑判断返回 JSON 或者 HTML 视图?
- Android 浏览网页:WebView 嵌入浏览器(浏览历史返回、自定义加载失败界面、支持缩放、获取标题栏)
- 网络请求在Genymotion中成功,真机中失败
- 关于使用Volley网络请求无返回结果的解决办法
- Android自定义之仿支付宝支付成功、失败状态的加载进度