android ListView 动态分页加载数据

参考文章:

http://blog.csdn.net/zimo2013/article/details/10263339

http://blog.csdn.net/zimo2013/article/details/12253301


 用ListView显示数据时,列表中数据量大时,加载和处理时间会明显变长,如果等到把所有数据都处理加载完成再显示出来,那程序的UI就非常糟糕了,很可能会随数据量的变大而变慢,这样的界面很不友好,我们无法接受。

 废话说完了,那怎么解决这个的问题呢?

 动态加载,分页加载。我不能在UI线程中做大量的读取、处理数据的动作,而是另开一个线程来做这件事。但是这样并不能保证显示及时,因为数据大时,时间仍会很长,怎么办,那我先处理一部分,先显示出来它们,后台再继续处理后面的数据,处理一部分,加载一部分。

 这就要用到Adapter和loader 类。

    static class AppsListItem{
        public Drawable icon = null;
        public String appLabel = "";
        public String summary = "";
        public String packageName = "";
        public int uid = -1;
        public int permCount = 0;
        public String key = "";

    }

    public static class AppListAdapter extends BaseAdapter {
        Activity mActivity;
        LayoutInflater mLayoutInflater;
        PackageManager mPackageManager;
        List<AppsListItem> mAppList;

        public AppListAdapter(Activity activity){
            mActivity = activity;
            mLayoutInflater = activity.getLayoutInflater();
            mPackageManager = activity.getPackageManager();
            mAppList = new ArrayList<AppsListItem>();
        }

        @Override
        public int getCount() {
            return (mAppList == null)? 0 : mAppList.size();
        }

        @Override
        public Object getItem(int position) {
            return mAppList.get(position);
        }

        public Object getItem(String packageName){
            for(AppsListItem appInfo : mAppList){
                if(appInfo.packageName.equals(packageName)){
                    return appInfo;
                }
            }
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        class ViewHolder{
            ImageView appIcon;
            TextView appName;
            TextView summary;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final ViewHolder viewHolder;
            if(convertView == null) {
                convertView = mLayoutInflater.inflate(R.layout.permission_preference_layout2, parent, false);
                viewHolder = new ViewHolder();
                viewHolder.appIcon = ((ImageView) convertView.findViewById(R.id.appIcon));
                viewHolder.appName = ((TextView) convertView.findViewById(R.id.appName));
                viewHolder.summary = ((TextView) convertView.findViewById(R.id.summary));
                convertView.setTag(viewHolder);
            }
            else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            final AppsListItem appInfo = mAppList.get(position);
            viewHolder.appIcon.setImageDrawable(appInfo.icon);
            viewHolder.appName.setText(appInfo.appLabel);
            viewHolder.summary.setText(appInfo.summary);

            return convertView;
        }

        public void setData(List<AppsListItem> selectedAppList) {
            mAppList.clear();

            if (selectedAppList != null) {
            Log.w(TAG,"APP list size "+selectedAppList.size());
            mAppList = selectedAppList;
            }
            notifyDataSetChanged();
        }

        public void addData(List<AppsListItem> selectedAppList) {

            if (selectedAppList != null) {
                Log.w(TAG,"APP list size "+selectedAppList.size());
                mAppList.addAll(selectedAppList);
            }
            notifyDataSetChanged();
        }

        public void removeItem(String packageName){
            AppsListItem item = (AppsListItem)getItem(packageName);
            if(item != null){
                mAppList.remove(item);
                notifyDataSetChanged();
            }
        }

        public void removeItem(int position){
            if(position < mAppList.size()){
                mAppList.remove(position);
                notifyDataSetChanged();
            }
        }

        public void addData(AppsListItem item) {
            if (item != null) {
                Log.w(LISTTAG,"add package "+item.packageName+" Label: "+item.appLabel);
                mAppList.add(item);
            }
            notifyDataSetChanged();
        }

    }
怎么用这个Adapter 呢,
 
 

onStart(){
...
listview.setAdapter(mAdapter); listview.setSelectionFromTop(mSaveIndex, mtop); listview.setOnScrollChangeListener(new View.OnScrollChangeListener() { @Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { //mAdapter.notifyDataSetChanged(); } }); listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mSaveIndex = listview.getFirstVisiblePosition(); View v = listview.getChildAt(0); mtop = (v == null) ? 0 : (v.getTop() - listview.getPaddingTop()); AppsListItem appinfo = (AppsListItem)mAdapter.getItem(position); if(appinfo != null){ final String mPackageName = appinfo.packageName; final int mUid = appinfo.uid; int permCnt = appinfo.permCount; Intent sendIntent = new Intent(); sendIntent.setAction("android.intent.action.MANAGE_APP_PERMISSIONS"); sendIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName); sendIntent.putExtra(Intent.EXTRA_UID, mUid); sendIntent.putExtra("hideInfoButton", true); startActivity(sendIntent); } } });
}


Adapter 需要loader 类来给它提供数据,它才给使listView 显示出来。

所以下面是loader 类,这个类是在后台读取并处理数据,处理完成一部分,给Adapter 来显示。但是分步处理这个过程需要借助

LoaderManager的。


    /**
     * A custom Loader that loads all of the installed applications.
     */
    public static class AppListLoader extends AsyncTaskLoader<List<AppsListItem>> {
        private int mCount = 0;
        private static int mOldCount = 0;
        private static int mSize = 0;
        private List<AppsListItem> items = null;
        private static List<ApplicationInfo> apps = new ArrayList<>();
        Boolean second = false;
        String SHAREDPREFERENCE_INSTALLED_PERMISSION_INFO = "PermissionInfos";
        public AppListLoader(Context context,int count) {
            super(context);
            mCount = count;
            Log.w(LISTTAG,"mCount "+mCount+" mOldCount "+mOldCount);
            if(items == null) {
                items = new ArrayList<AppsListItem>();
            }
            //You Should confirm FIRSTLOAD (11) num diff from others (5)
            if(mCount ==FIRSTLOAD ) {
                mOldCount = 0;
            }
        }

        @Override
        public List<AppsListItem> loadInBackground() {
            Log.w(LISTTAG,"===============loadInBackground =================");
            return buildList();
        }

        @Override
        protected void onStartLoading() {
            Log.w(LISTTAG,"===============onStartLoading =================");
            forceLoad();
        }

        public List<AppsListItem> buildList() {
            int permcount = 0;
            ApplicationInfo appInfo;
            //Context context = getContext();
            PackageManager pm = mContext.getPackageManager();
            int index = 0;
            CtaUtils mCtaUtils = new CtaUtils(mContext);


            if(apps.size()==0 ) {
                apps = pm.getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES);//Utils.getAllInstalledApplications(context);
            }

            mSize = apps.size();
            //Log.w(LISTTAG,"mCount "+mCount+" mOldCount "+mOldCount+" mSize "+mSize);
            SharedPreferences permissionInfos = mContext.getSharedPreferences(SHAREDPREFERENCE_INSTALLED_PERMISSION_INFO, 0);
            SharedPreferences.Editor editor = permissionInfos.edit();
            for(int i=0;i<mSize;i++){
                index = mOldCount+i;
                if(index <mSize) {
                    appInfo = apps.get(index);
                    if(shouldSkipFirst(pm,appInfo)){
                        //Log.w(LISTTAG, "shouldSkipFirst I " + i+" index" +index);
                        continue;
                    }

                    String preKey = appInfo.packageName + "|" + appInfo.uid;
                    permcount = permissionInfos.getInt(preKey, -1);
                    if (permcount < 0) {
                        //Log.w(LISTTAG, "getCount I " + i+" index "+index);
                        permcount = getPermissionCountInner(appInfo.packageName);
                        permcount = permcount + mCtaUtils.getCTARecords(appInfo.uid, appInfo.packageName);
                        editor.putInt(preKey, permcount);
                        editor.commit();
                    }

                    if (shouldSkip( permcount)) {
                        //Log.w(LISTTAG, "shouldSkip I " + i+" index" +index);
                        continue;
                    }

                    AppsListItem item = new AppsListItem();
                    item.appLabel = appInfo.loadLabel(pm).toString();
                    item.packageName = appInfo.packageName;
                    item.uid = appInfo.uid;
                    item.icon = appInfo.loadIcon(pm);
                    item.permCount = permcount;
                    item.summary = "" + permcount + mContext.getResources().getString(R.string.permission_count);
                    item.key = appInfo.packageName + "|" + appInfo.uid;
                    if (item.icon == null) {
                        item.icon = mContext.getResources().getDrawable(android.R.drawable.sym_def_app_icon);
                    }

                    items.add(item);
                    mCount--;
                    if(mCount==0)
                        break;

                }else{
                    Log.e(LISTTAG, "Out of index! mOldCount " + mOldCount+" i "+i+" mSize "+mSize);
                    loadcomplete = true;
                    apps.clear();
                    break;
                }
            }
            //Log.w(LISTTAG,"index "+index+" mCount "+mCount);
            mOldCount = (index+1);

/*            try {
                Collections.sort(items, APP_COMPARATOR);
            }
            catch (Exception e) {
            }*/

            return items;
        }

        private  int getPermissionCountInner(String packageName ){
            int cnt = 0;
            mPermSet.clear();
            PackageInfo mPackageInfo = getPackageInfo(getContext(), packageName);

            if(mPackageInfo ==null || mPackageInfo.requestedPermissions == null) {
                return cnt;
            }
            for (String requestedPerm : mPackageInfo.requestedPermissions) {
                //Log.w(TAG,"requestedPerm "+requestedPerm);
                PermissionInfo permInfo = null;
                try {
                    permInfo = mContext.getPackageManager().getPermissionInfo(requestedPerm, 0);
                } catch (PackageManager.NameNotFoundException e) {
                    //Log.w(TAG, "NameNotFoundException "+e.getLocalizedMessage());
                }

                if (permInfo != null && permInfo.group != null) {
                    mPermSet.add(permInfo.group);
                }
            }

            for(String groupName : mPermSet){
                switch(groupName){
                    case PERMISSION_CALENDER_GROUP_NAME:
                    case PERMISSION_STORAGE_GROUP_NAME:
                    case PERMISSION_BODY_SENSORS_GROUP_NAME:
                    case PERMISSION_SMS_GROUP_NAME:
                    case PERMISSION_CONTACTS_GROUP_NAME:
                    case PERMISSION_PHONE_GROUP_NAME:
                    case PERMISSION_CAMERA_GROUP_NAME:
                    case PERMISSION_MICROPHONE_GROUP_NAME:
                    case PERMISSION_LOCATION_GROUP_NAME:
                        cnt++;
                        break;
                }
            }

            return cnt;
        }

/*        public static final Comparator<AppsListItem> APP_COMPARATOR = new Comparator<AppsListItem>() {
            @Override
            public int compare(AppsListItem item1, AppsListItem item2) {
                String temp = "" + item2.switchState;
                int res = temp.compareTo("" + item1.switchState);
                if(res == 0){
                    if(item2.suggestOpenText.compareTo(item1.suggestOpenText) == 0) {
                        res = 0;
                    }else if(item2.suggestOpenText.compareTo(item1.suggestOpenText) > 0){
                        res = 1;
                    }else{
                        res = -1;
                    }
                }
                return res;
            }
        };*/

    }

所以我们需要实现LoaderManager 的几个callback: onCreateLoader, onLoadFinished, onLoaderReset
在这几个callback中来把loader 

public class MyActivity extends FrameFrgment  implements
        LoaderManager.LoaderCallbacks<List<MyActivity.AppsListItem>> {

onCreate{
...
 mAdapter= new AppListAdapter(getActivity());
Bundle args = new Bundle();
args.putInt(loadcount,FIRSTLOAD);
getLoaderManager().initLoader(0, args, this);

...}
...
private void restartLoader(){
    Bundle args = new Bundle();

    args.putInt("count",LOADNUM);
    getLoaderManager().restartLoader(0,args,this);
    Log.w(TAG,"===============onLoaderReset =================");
}

@Override
public Loader<List<AppsListItem>> onCreateLoader(int id, Bundle args) {
    int count = 0;
    if(args != null) {
        count = args.getInt(loadcount, 10);
    }
    mAppListLoader = new AppListLoader(getActivity(),count);
    return mAppListLoader;
}

@Override
public void onLoadFinished(Loader<List<AppsListItem>> loader, List<AppsListItem> data) {
    try {
        if(mAdapter.getCount()==0) {
            mAdapter.setData(data);
            
            if(!loadcomplete) {
                //You Should confirm FIRSTLOAD (11) num diff from others (5)
                restartLoader();
            }
        }
        else {
            mAdapter.addData(data);
            
            if(!loadcomplete) {
                //You Should confirm FIRSTLOAD (11) num diff from others (5)
                restartLoader();
            }
        }
        setLoading(false,true);
    }catch (Exception err){
        Log.d(LISTTAG, "AppAutoStartList-->onLoadFinished", err);
    }
}

@Override
public void onLoaderReset(Loader<List<AppsListItem>> loader) {
    // Clear the data in the adapter.
    //mAdapter.setData(null);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值