2 qq 30952451 qq_30952451 于 2016.03.05 13:51 提问

AsyncTask中怎么让doInBackground执行完再执行onPostExecute方法

各位好,我在做一个手机缓存的扫描,需要在doInBackground()里扫描应用信息,并通过publishProgress()把应用传给onProgressUpdate(),并刷新进度条,并把没有缓存的应用显示出来,最后把有缓存的集合在onPostExecute()方法中置顶显示,可是doInBackground()没执行完,onPostExecute()就执行完了,求解决,代码如下:

package com.yufei.testmobilesafe.activities;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.yufei.testmobilesafe.R;
import com.yufei.testmobilesafe.base.BaseActivity;
import com.yufei.testmobilesafe.domain.AppInfo;

public class SpeedSystemActivity extends BaseActivity {

private ImageView mIvLine;
private TextView mTvCache;
private TextView mTvPackageName;
private ProgressBar mPdProgress;
private ImageView mIvIcon;
private List<View> cacheVeiws=new ArrayList<View>();
private List<AppInfo> mCache = new ArrayList<AppInfo>();
private Context mContext;
private LinearLayout mllItems;
private Button bt_clear;

@Override
public void initView() {

    setContentView(R.layout.activity_clean_cache);
    mContext = this;
    mllItems = (LinearLayout) findViewById(R.id.ll_items);
    mIvIcon = (ImageView) findViewById(R.id.iv_icon);
    mPdProgress = (ProgressBar) findViewById(R.id.pd_progress);
    mTvPackageName = (TextView) findViewById(R.id.tv_pacakgename);
    mTvCache = (TextView) findViewById(R.id.tv_cachesize);
    mIvLine = (ImageView) findViewById(R.id.iv_line);
    bt_clear = findView(R.id.bt_clear);
}

@Override
public void initListener() {

    bt_clear.setOnClickListener(this);
}

@Override
public void initData() {

    AsyncTask<Void, AppInfo, Void> asyncTask = new AsyncTask<Void, AppInfo, Void>() {

        private int total = 1;
        private int progress = 0;

        /***
         * 方法 准备
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            startAnimation();
            // 准备工作
            mPdProgress.setMax(100);
            mPdProgress.setProgress(0);
            mTvCache.setText("缓存大小:0.00");
            mTvCache.setVisibility(View.INVISIBLE);
            mTvPackageName.setText("");
            cacheVeiws.clear();
        }

        /***
         * 方法
         * 
         * @param params
         * @return 子线程后台运行
         */
        @Override
        protected Void doInBackground(Void... params) {
            // 加载数据
            mCache.clear();
            loadData();// 边加载还得边更新
            return null;
        }

        /***
         * 方法
         * 
         * @param result
         *            加载结束
         */
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            cleanAnimation();
            // 加载结束
            mTvCache.setVisibility(View.VISIBLE);
            int cache = 0;
            for (AppInfo item : mCache) {
                cache += item.cacheSize;
            }
            mTvCache.setText("缓存大小:" + Formatter.formatFileSize(mContext, cache));

           //添加到顶部
            for(View view:cacheVeiws)
            {
                mllItems.addView(view, 0);// 顶部
            }
            cacheVeiws.clear();
        }

        /***
         * 方法 加载过程中的更新
         * 
         * @param values
         */
        @Override
        protected void onProgressUpdate(AppInfo... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
            final AppInfo appInfo = values[0];
            mCache.add(appInfo);
            // 更新
            mIvIcon.setImageDrawable(appInfo.icon);
            mTvPackageName.setText(appInfo.appName);
            progress += 1;

            int percent = (int) (progress * 100f / total + 0.5f);
            // 更新进度条
            mPdProgress.setProgress(percent);
            View itemView = View.inflate(mContext, R.layout.item_cache_info, null);

            ImageView ivIcon = (ImageView) itemView.findViewById(R.id.iv_icon);
            TextView appName = (TextView) itemView.findViewById(R.id.tv_appname);
            TextView cacheSize = (TextView) itemView.findViewById(R.id.tv_cachesize);
            TextView clean = (TextView) itemView.findViewById(R.id.tv_clean);
            ivIcon.setImageDrawable(appInfo.icon);
            appName.setText(appInfo.appName);
            cacheSize.setText(Formatter.formatFileSize(mContext, appInfo.cacheSize));
            // 有缓存要显示扫把
            if (appInfo.cacheSize > 0) {
                clean.setVisibility(View.VISIBLE);

// mllItems.addView(itemView, 0);// 顶部
cacheVeiws.add(itemView);
clean.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {

                        Intent intent = new Intent();
                        intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
                        intent.addCategory("android.intent.category.DEFAULT");
                        intent.setData(Uri.parse("package:" + appInfo.packageName));
                        startActivity(intent);
                    }
                });
            } else {
                clean.setVisibility(View.INVISIBLE);
                mllItems.addView(itemView,0);
            }
        }

        /***
         * 方法
         */
        private void loadData() {
            // data/data/包名/cache
            // 查询所有的安装程序
            PackageManager packageManager = getPackageManager();
            // 安装记录
            List<PackageInfo> list = packageManager.getInstalledPackages(0);
            total = list.size();
            Method method = null;
            try {
                Class<?> clz = Class.forName("android.content.pm.PackageManager");
                // 如果碰到一个类找不到 1.是@hide 反射 2.可能是aidl 复制到对应包下 -工具自动生成接口与实现Stub
                Method[] declaredMethods = clz.getDeclaredMethods();

                for (Method m : declaredMethods) {
                    if (TextUtils.equals(m.getName(), "getPackageSizeInfo") && m.getParameterTypes().length == 2) {
                        method = m;
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            for (PackageInfo item : list) {
                try {
                    IPackageStatsObserver stub = new IPackageStatsObserver.Stub() {
                        // 统计完一个cache大小的时候
                        @Override
                        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {
                            try {
                                // 封装
                                AppInfo appInfo = new AppInfo();
                                appInfo.cacheSize = pStats.cacheSize;
                                appInfo.packageName = pStats.packageName;
                                // 图标与应用名
                                PackageManager pm = getPackageManager();
                                PackageInfo packageInfo = pm.getPackageInfo(appInfo.packageName, 0);
                                ApplicationInfo applicationInfo = packageInfo.applicationInfo;
                                appInfo.icon = applicationInfo.loadIcon(pm);
                                appInfo.appName = applicationInfo.loadLabel(pm).toString();

                                // 提交给页面显示
                                publishProgress(appInfo);// -->onProgressUpdate
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    };
                    method.invoke(packageManager, item.packageName, stub);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    asyncTask.execute();
}

@Override
public void process(View view) {

    switch (view.getId()) {
    //清理缓存
    case R.id.bt_clear:

        clearApps();
        break;

    }
}


public void clearApps() {
    try {
        IPackageDataObserver stub = new IPackageDataObserver.Stub() {
            // 所有应用cache数据已被清空
            @Override
            public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 重新查询
                        Toast.makeText(mContext, "清理干净了!", Toast.LENGTH_SHORT).show();
                        finish();

                    }
                });
            }
        };
        PackageManager packageManager = getPackageManager();
        Class<?> clz = Class.forName("android.content.pm.PackageManager");
        Method[] methods = clz.getDeclaredMethods();
        Method method = null;
        for (Method m : methods) {
            if (TextUtils.equals("freeStorageAndNotify", m.getName())) {
                method = m;
                break;
            }
        }
        if (method != null) {
            method.invoke(packageManager, Long.MAX_VALUE, stub);
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}


private void startAnimation() {
    int type = TranslateAnimation.RELATIVE_TO_PARENT;
    TranslateAnimation ta = new TranslateAnimation(type, 0f, type, 0f, type, 0f, type, 1f);
    // 时长
    ta.setDuration(1000);
    ta.setRepeatCount(Animation.INFINITE);//
    ta.setRepeatMode(Animation.REVERSE);
    mIvLine.startAnimation(ta);
}

private void cleanAnimation() {
    mIvLine.clearAnimation();
}

}

3个回答

u014673901
u014673901   2016.04.07 15:49

我最近也遇到同样的问题,还没有解决,貌似是子线程与主线程执行不同步问题

u014673901
u014673901   2016.04.07 17:49
看懂了,是这样的,你在loadData()方法加载数据的时候用到 IPackageStatsObserver stub = new IPackageStatsObserver.Stub() {},这个类执行onGetStatsCompleted() 方法时会开辟一个子线程,在子线程中进行相关操作。这样的话相当于你调用AsyncTask的doInBackground()方法在子线程中执行任务时,这个子线程有开辟了一个子线程中执行耗时操作,而onPostExecute()之后在doInBackground()的线程执行完成后才执行,所有不是等onGetStatsCompleted()这个线程执行完才执行,所以,AppInfo 的信息无法在onPostExecute()里面更新。
解决方案:等onGetStatsCompleted()执行完再去执行onPostExecute(),可以设置flag,等onGetStatsCompleted()执行完后flag改为true,然后通知onPostExecute()进行执行。
m0_37307670
m0_37307670 嗯,66666
4 个月之前 回复
j550341130
j550341130   2016.03.05 14:13

doInBackground方法不要返回null。

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!