美文网首页孚睿科技·ANDROID知识总结Android
如何快速实现app网络加载中网络异常、空数据等页面?如何实现下拉

如何快速实现app网络加载中网络异常、空数据等页面?如何实现下拉

作者: OlivineVip | 来源:发表于2016-09-20 20:24 被阅读1577次
    • 在项目开发中如何快速处理网络加载中错误页面、空数据页面、网络异常等页面?
    • 在项目开发中如何快速实现“上拉刷新”与“加载更多”?
    过去做法:
    • NetFragment 处理网络加载的页面
      • 采用“约定优于配置原则”,直接规定好错误页面、空数据页面、网络异常等页面的Id
      • NetFragment负责加载数据、控制错误页面、空数据页面、网络异常页面显示隐藏
    • ListNetFragment处理下拉刷新和加载更多的界面
      • 处理下拉刷新和加载更多的逻辑
      • 控制加载数据、控制错误页面、空数据页面、网络异常页面显示隐藏

    存在的问题:
    - 下拉刷新如果失败,listview上面的headView需要保留(不能实现)
    - 下拉刷新加载过程中,上拉刷新出现崩溃Bug
    - 控制逻辑C和页面展示V 没有真正分离,可扩展性差

    现在做法:
    • 剥离网络加载控制逻辑
    • 从NetFragment中抽取NetController,处理网络加载控制逻辑
    • 从ListNetFragment中抽取ListNetController,处理下拉刷新和加载更多的逻辑

    • 重写NetFragment,实现NetController与各种页面的绑定

    • 重写ListNetFragment,实现ListNetController与各种页面的绑定

    资源下载:
    使用教程
    1. NetFragment
    • 绘制Xml eg:fragment_exam
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/net_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        //加载中   id为net_progress
        <LinearLayout
            android:id="@+id/net_progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:orientation="vertical">
    
            <ProgressBar
                style="?android:attr/progressBarStyle"
                android:layout_width="200dip"
                android:layout_height="wrap_content"
                android:indeterminate="true"
                android:indeterminateOnly="true" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="数据正在加载中……"
                android:textColor="#000000" />
        </LinearLayout>
        
        //数据为空的界面  id为net_no_result
        <TextView
            android:id="@+id/net_no_result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="数据为空"
            android:textColor="#000000" />
    
        //数据错误  id为net_error
        <TextView
            android:id="@+id/net_error"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="数据出错"
            android:textColor="#000000" />
            
         //参数错误  id为net_fail
        <LinearLayout
            android:orientation="vertical"
            android:id="@+id/net_fail"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <include  layout="@layout/nonata_2"/>
    
        </LinearLayout>
    
        //网络异常 id为net_cannot_access
        <LinearLayout
            android:orientation="vertical"
            android:id="@+id/net_cannot_access"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <include  layout="@layout/nonata_2"/>
        </LinearLayout>
    
    
         //有数据  id为net_result
        <LinearLayout
            android:orientation="vertical"
            android:id="@+id/net_result"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <include  layout="@layout/nonata_2"/>
        </LinearLayout>
    
    </FrameLayout>
    
    • 网络加载的Fragment继承NetFragment eg: ExamFragment
    public class ExamFragment extends NetFragment<GetSelfOfficialExamNameNetResultInfo> {
        private static final String TAG = ExamFragment.class.getSimpleName();
        @Bind(B.id.nav_go_back)
        ImageView navGoBack;
        @Bind(B.id.nav_tv_title)
        TextView navTvTitle;
        @Bind(B.id.nav_tv_right)
        TextView navTvRight;
        @Bind(B.id.tv_exam_choose_1)
        TextView tvExamChoose1;
        @Bind(B.id.tv_exam_choose_2)
        TextView tvExamChoose2;
        @Bind(B.id.ll_item_0)
        LinearLayout llItem0;
        @Bind(B.id.ll_item_1)
        LinearLayout llItem1;
        @Bind(B.id.tv_item_0_name)
        TextView tvItem0Name;
        @Bind(B.id.tv_item_1_name)
        TextView tvItem1Name;
        private GetSelfOfficialExamNameNetResultInfo resultInfo;//网络请求的数据模型
    
         /**
         * 获取布局Id
         */
        @Override
        public int getLayoutId() {
            return R.layout.fragment_exam;
        }
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = super.onCreateView(inflater, container, savedInstanceState);
            navGoBack.setVisibility(View.INVISIBLE);
            navTvTitle.setText("考点儿");
            navTvRight.setText("考试管理");
            return rootView;
        }
    
        /**
         * 网络请求
         */
        @Override
        public GetSelfOfficialExamNameNetResultInfo onDoInBackgroundSafely() {
            GetSelfOfficialExamNameNetResultInfo.Request params = new GetSelfOfficialExamNameNetResultInfo.Request();
            return RepositoryCollection.getSelfOfficialExamName(params);
        }
    
        /**
         *  请求成功时 
         */
        @Override
        protected void onDisplayResult(GetSelfOfficialExamNameNetResultInfo resultInfo) {
            this.resultInfo = resultInfo;
            tvItem0Name.setText(resultInfo.getSelfExamName());
            tvItem1Name.setText(resultInfo.getOfficialExamName());
        }
    
    }
    
    
    2 ListNetFragment 的使用
    • 绘制XML eg: fragment_teacher
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/net_result"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">
    
            <ListView
                android:id="@+id/net_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginLeft="@dimen/width_720_1280_20"
                android:layout_marginRight="@dimen/width_720_1280_20"
                android:background="@color/bg_window"
                android:clipToPadding="false"
                android:divider="@color/color_underline"
                android:dividerHeight="@dimen/hs1" />
    
        </android.support.v4.widget.SwipeRefreshLayout>
    
    </FrameLayout>
    
    • 绘制异常界面的Xml 作为ListView的item eg:net_list_abnormal_layout
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:id="@+id/net_no_result"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="@dimen/hs200">
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:clickable="false"
                android:gravity="center"
                android:text="@string/net_no_result"
                android:textColor="#000000" />
    
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/net_error"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="@dimen/hs200">
    
            <include layout="@layout/nonata_2" />
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/net_fail"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ndroid:orientation="vertical"
            android:paddingTop="@dimen/hs200">
    
            <include layout="@layout/nonata_2" />
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/net_cannot_access"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="@dimen/hs200">
            <include layout="@layout/nonata_2" />
        </LinearLayout>
    
    </FrameLayout>
    
    
    • 继承ListNetFragment
    public class TeacherFragment extends ListNetFragment<AppArticleModel> {
        private static final String TAG = TeacherFragment.class.getSimpleName();
        @Bind(B.id.nav_go_back)
        ImageView navGoBack;
        @Bind(B.id.nav_tv_title)
        TextView navTvTitle;
        @Bind(B.id.iv_teacher_photo)
        ImageView ivTeacherPhoto;
        @Bind(B.id.tv_teacher_name_1)
        TextView tvTeacherName1;
        @Bind(B.id.tv_teacher_name_2)
        TextView tvTeacherName2;
        @Bind(B.id.tv_teacher_name_3)
        TextView tvTeacherName3;
        @Bind(B.id.ll_log_status)
        LinearLayout llLogStatus;
        private int teacherId;
        private DisplayImageOptions options;
    
        private AppTeacherModel teacherModel;
    
        @Override
        public int getLayoutId() {
            return R.layout.fragment_teacher;
        }
      // 获取网络异常 空数据 等界面布局
        @Override
        public int getAbnormalViewLayoutId() {
            return R.layout.net_list_abnormal_layout;
        }
    
      
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = super.onCreateView(inflater, container, savedInstanceState);
    
          //  mNetController.setPageSize(20);        //   设置每次加载个数  默认为10
            mNetController.addHeadView(headView);  //  添加头布局  没有可以不写
            mNetController.setListAdapter();       // 注: 在addHeadView(headView)之后,
          //  mNetController.setRefreshEnable(false); //能否下拉刷新  默认为true
          //  mNetController.setLoadMoreEnable(false);//能否加载更多  默认为true
            
            return rootView;
        }
    
        @Override
        protected ListNetResultInfo<AppArticleModel> onDoInBackgroundSafely(int i, int i1) {
            GetTeacherInfoNetResultInfo.Request params = new GetTeacherInfoNetResultInfo.Request();
            PageModel pageModel = new PageModel();
            pageModel.setStartIndex(i);
            pageModel.setPageSize(i1);
            params.setPage(pageModel);
            params.setTeacherId(teacherId);
            return RepositoryCollection.getTeacherInfo(params);
        }
    
      // list item任意一TextView的Id
      
        @Override
        public int getItemTextViewResourceId() {
            return R.id.tv_content;
        }
    
      //list item的布局
        @Override
        public int getItemLayoutId() {
            return R.layout.item_list_teacher;
        }
    
        //用于 处理list的item
        @Override
         public View bindView(int i, View view, ViewGroup viewGroup) {
             ViewHolder holder;
             if (view == null) {
                 view = View.inflate(getContext(), R.layout.item_list_teacher, null);
             }
             holder = (ViewHolder) view.getTag();
             if (holder == null) {
                 holder = new ViewHolder(view);
                 view.setTag(holder);
             }
             final AppArticleModel model = getItem(i);
             
             holder.tvContent.setText(model.getTitle());
             String shareTime = TimeUtil.longToString(model.getCreateDate(), TimeUtil.FORMAT_DATE);
             holder.tvShareTime.setText(shareTime);
             holder.tvPreview.setText("" + model.getViewNum());
            
             return view;
         }
     
         class ViewHolder {
             @Bind(B.id.tv_title)
             TextView tvTitle;
             @Bind(B.id.tv_content)
             TextView tvContent;
             @Bind(B.id.tv_share_time)
             TextView tvShareTime;
             @Bind(B.id.tv_preview)
             TextView tvPreview;
             @Bind(B.id.tv_item_teacher_zambia)
             TextView tvItemTeacherZambia;
             @Bind(B.id.ll_item)
             LinearLayout ll_item;
     
             ViewHolder(View view) {
                 ButterFork.bind(this, view);
             }
         }
    
    }
    
    解决SwipeRefreshLayout与ViewPager 的滑动冲突

    通过重写SwipeRefreshLayout的onInterceptTouchEvent方法

    public class BannerSwipeRefreshLayout extends SwipeRefreshLayout {
        public BannerSwipeRefreshLayout(Context context) {
            super(context);
        }
    
        public BannerSwipeRefreshLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        float lastx = 0;
        float lasty = 0;
        boolean ismovepic = false;
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                lastx = ev.getX();
                lasty = ev.getY();
                ismovepic = false;
                return super.onInterceptTouchEvent(ev);
            }
    
            final int action = MotionEventCompat.getActionMasked(ev);
    
            int x2 = (int) Math.abs(ev.getX() - lastx);
            int y2 = (int) Math.abs(ev.getY() - lasty);
    
            //滑动图片最小距离检查
            if (x2 > y2) {
                if (x2 >= 100) ismovepic = true;
                return false;
            }
    
            //是否移动图片(下拉刷新不处理)
            if (ismovepic) {
                return false;
            }
            boolean isok = super.onInterceptTouchEvent(ev);
    
            return isok;
        }
    }
    
    

    相关文章

      网友评论

      本文标题:如何快速实现app网络加载中网络异常、空数据等页面?如何实现下拉

      本文链接:https://www.haomeiwen.com/subject/ptvoettx.html