博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
开源项目AndroidReview学习小结(2)
阅读量:6947 次
发布时间:2019-06-27

本文共 7232 字,大约阅读时间需要 24 分钟。

下拉刷新

下拉刷新常见的有俩大类,和 前者是国外的一大神写的出现的比较早,不过好像已经停止维护了,后者是国内的一个大神写的功能很强大,这个项目使用的是后者(MaterialHeader类型刷新),首先这里又封装了一层BasePutToRefreshFragment用来进行下拉刷新的操作 

下面简单介绍下这个控件的使用,首先是布局文件中fragment_review.xml

在BasePutToRefreshFragment.中的initDoRefreshView()中开始使用该控件

private void initDoRefreshView() {        //ptr控件的使用        mPtrFrameLayout = (PtrFrameLayout) mRootView.findViewById(R.id.layout_refresh);        // header        MaterialHeader header = new MaterialHeader(getContext());        int[] colors = getResources().getIntArray(R.array.google_colors);        header.setColorSchemeColors(colors);        header.setLayoutParams(new PtrFrameLayout.LayoutParams(-1, -2));        header.setPadding(0, (int) TDevice.dpToPixel(15), 0, (int) TDevice.dpToPixel(10));        header.setPtrFrameLayout(mPtrFrameLayout);        mPtrFrameLayout.setLoadingMinTime(1000);        mPtrFrameLayout.setDurationToCloseHeader(1500);        mPtrFrameLayout.setHeaderView(header);        mPtrFrameLayout.addPtrUIHandler(header);        mPtrFrameLayout.setPinContent(true);        mPtrFrameLayout.disableWhenHorizontalMove(true);        mPtrFrameLayout.setPtrHandler(new PtrHandler() {            @Override            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {                return PtrDefaultHandler.checkContentCanBePulledDown(frame, mListView, header);            }            @Override            public void onRefreshBegin(final PtrFrameLayout frame) {                Logger.e("list is load data by net");                //先判断是否是自动刷新                if (frame.isAutoRefresh()) {                    if (mPtrFrameLayout.isRefreshing()) {                        mPtrFrameLayout.refreshComplete();                    }                    //加载刷新布局                    mLoadingLayout.setLoadingLayout(LoadingLayout.NETWORK_LOADING);                }                sPutUpState = PULL_UP_STATE_NONE;                // 这里做下拉刷新操作                requestDataByNet(REFRESH_TYPE_PULL);            }        });    }

详细的使用可以参见如下链接 不过使用开源项目还是需要尽量搞清楚其中实现的机制。 

这里有俩个关键函数

  • mLoadingLayout.setLoadingLayout(LoadingLayout.NETWORK_LOADING); 
    加载刷新布局,这在下面会介绍
  • requestDataByNet(REFRESH_TYPE_PULL); 
    网络请求数据,这里还指明了类型用来区分是上拉还是下拉,在这个基类中将这个方法声明为抽象方法留在继承类中实现
public abstract void requestDataByNet(int actionType);
  • listview的高效加载 
    通常的方式就是在滑动进行监听 onScrollStateChanged方法中对不同状态判断其中主要有三个状态 
    SCROLL_STATE_FLING,SCROLL_STATE_TOUCH_SCROLL,SCROLL_STATE_IDLE,一般是在滑动停止时(SCROLL_STATE_IDLE)才加载listview的数据
@Override            public void onScrollStateChanged(AbsListView view, int scrollState) {                switch (scrollState) {                    //在滑动停止时加载                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:                        if (isItemfullScreen) {                            if (sPutUpState == PULL_UP_STATE_NONE && isLoadMore) {                                Logger.e("list is load more data");                                pullUpLoadData();                            }                        }                        break;                }            }

若要实现listview的加载更多还需要重写onScroll方法,这里通过一个标志位isItemfullScreen来标识

@Override            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {                //firstVisibleItem -屏幕上显示的第一个item                //visibleItemCount -屏幕上一共显示item的数目                //totalItemCount -目前listview 一共有多少个itme                if (totalItemCount > visibleItemCount) {                    isItemfullScreen = true;                } else {                    isItemfullScreen = false;                }            }

其中加载更多需要重新定义一个布局,利用listview.addFooterView(layout)来实现,

不同状态的页面

这个非常常见,比如没有网络时页面显示一个样式,正在刷新显示一个样式,在上面的下来刷新中已经体现在mLoadingLayout.setLoadingLayout(LoadingLayout.NETWORK_LOADING); 可以看出,这种需求的实现是通过定义一个自定义控件protected LoadingLayout mLoadingLayout;,该自定义控件通过add(view)方式将自己加到页面中,其中在容器(viewgroup子类)中增加布局使用add,在widget中使用set这个要注意。这个控件会根据当前传入的状态通过switch来选择自己展现的状态,具体在LoadingLayout.java中,比较简单就不贴代码了。 

这里通过单独控件的形式将各类状态分离出来,比较好操作

数据缓存

核心思想是通过序列化将数据存入到file文件中 

- 读取缓存,核心类ReadCacheAsyncTask 
读取是在ReviewFragment中进行处理的,首先实现了BasePutToRefreshFragment.java中的抽象方法public abstract void readCache();该方法作在fragment创建时候会调用。

  • 存储缓存,核心类SaveCacheAsyncTask 
    存储是在下来刷新具体实现时调用,在请求数据requestPointByUnits中 
    其中使用CacheHelper.java中的readObject和saveObject与之配合使用。

首先这俩个核心类的名称就可以看出这是使用AsynTask来进行处理,为了防止内存泄漏,这里都做了弱引用 

先来看存储缓存

public class SaveCacheAsyncTask extends AsyncTask
{
private WeakReference
mContext; private Serializable seri; private String cacheKey; public SaveCacheAsyncTask(Context context, Serializable seri, String cacheKey) { mContext = new WeakReference
(context); this.seri = seri; this.cacheKey = cacheKey; } @Override protected Void doInBackground(Void... params) { CacheHelper.saveObject(mContext.get(), seri, cacheKey); return null; }}

其中CacheHelp中的saveObject就是做了一下存储

public static boolean saveObject(Context context, Serializable ser,                                     String file) {        FileOutputStream fos = null;        ObjectOutputStream oos = null;        try {            fos = context.openFileOutput(file, Context.MODE_PRIVATE);            oos = new ObjectOutputStream(fos);            oos.writeObject(ser);            oos.flush();            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        } finally {            try {                oos.close();            } catch (Exception e) {            }            try {                fos.close();            } catch (Exception e) {            }        }    }

同理保存过程原理一致,关键在于CacheHelp中的判断是否缓存失效函数,根据文件的两次时间戳比对是否失效,在DetailActvity中选择是否沿用缓存

/**     * 判断缓存是否已经失效     */    public static boolean isCacheDataFailure(Context context, String cachefile) {        File data = context.getFileStreamPath(cachefile);        if (!data.exists()) {            return false;        }        long existTime = System.currentTimeMillis() - data.lastModified();        boolean failure = false;        if (TDevice.getNetworkType() == TDevice.NETTYPE_WIFI) {            failure = existTime > Settings.getInt(Settings.CACHE_OVERTIME_WIFI,30) * 60 * 1000 ? true : false;        } else {            failure = existTime > Settings.getInt(Settings.CACHE_OVERTIME_OTHER,2) * 24 * 60 * 60 * 1000 ? true : false;        }        return failure;    }

一些细节

这个tab使用时listview中嵌套gridview的方式,这里就需要重写gridview的onMreasure的高度否则就会显示不全,重写也比较简单

public class GridViewEx extends GridView {
public GridViewEx(Context context) { this(context, null); } public GridViewEx(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GridViewEx(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }}

ok,写不动了额

转自:http://blog.csdn.net/xsf50717/article/details/51006605

你可能感兴趣的文章
nginx最简单的反向代理脚本
查看>>
ECharts2.0 学习笔记
查看>>
我的友情链接
查看>>
PyCharm 中文注释报错 SyntaxError: Non-ASCII character
查看>>
实用的正则表达式
查看>>
centos5.5 bind快速安装总结
查看>>
Android 动态创建Tab
查看>>
一个数据库操作类, 覆盖了基本数据操作。
查看>>
如何避免JS变量全局污染二
查看>>
什么是Silverlight
查看>>
Java不同的代码块的区别
查看>>
我的友情链接
查看>>
通配符,自己理解的
查看>>
分享时刻计划
查看>>
FWC无法连接ISA
查看>>
MySql 报错 Column count doesn't match value count at row 1 分析
查看>>
Rsync 文件同步(windows下安装部署)
查看>>
MySQL - 修改数据表
查看>>
HBase 系统架构
查看>>
源码安装Mysql 5.6.21 错误
查看>>