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
11 个月之前 回复
j550341130
j550341130   2016.03.05 14:13

doInBackground方法不要返回null。

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
AsyncTask中执行完doInBackground不执行onPostExecute
在项目中遇到一个很奇怪的问题, 在做软件升级检查的时候,调用到AsynTask,在android2.3,android2.2  ....(小于android2.3版本系统) 发现跑完doInBackground回调函数之后, 程序不再往下运行onPostExecute了; 但是如果程序运行在android4.0以后的版本上面, 是可以正常运行onPostExecute回调函数的。 在网上看了半天
工作随笔:BaseAsyncTask执行完doInBackground不执行onPostExecute
项目使用AndroidAppFrameWork的BaseAsyncTask做了大量的网络请求,今天在做版本兼容(测试机版本4.0.4)的时候,没注意在哪里做了什么修改,onPostExecute方法突然都不执行了,一步一步的还原,发现还是有问题,弄的头好大。 万事不决问度娘,看了好多小伙伴的文章,还是没发现问题的原因所在,又新建了Demo做测试,发现Demo里BaseAsyncTask的onPo
AsyncTask的doInBackground方法延迟执行的问题
今天发现一个很奇葩的bug,当使用asyncTask去执行后台下载任务时发现其他的接口都不好用了,一直在加载中,debug发现doInBackground方法不执行,要等到下载任务完成才会正常执行。。。在网上搜发现了此贴解决了这个问题 本文转自 http://blog.csdn.net/mddy2001/article/details/17127065  故事背景:一个HttpURL
AsyncTask 使用心得
之前一直使用Handler,最近在试着使用AsyncTask 时由于几个细节没注意老是不顺利。 1、doInBackground是用来执行费时的操作,如下载……,但不能在doInBackground中更新UI界面,如果想要更新UI界面,需要在onPostExecute中执行 2、doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声
Android基础之AsyncTask的doInBackground方法参数详解
AsyncTask的使用方法和理解 1、对于耗时的操作,我们的一般方法是开启“子线程”。如果需要更新UI,则需要使用handler 2、如果耗时的操作太多,那么我们需要开启太多的子线程,这就会给系统带来巨大的负担,随之也会带来性能方面的问题。在这种情况下我们就可以考虑使用类AsyncTask来异步执行任务,不需要子线程和handler,就可以完成异步操作和刷新UI。 3、AsyncTas
AsyncTask引发的一个问题:doInBackground()未及时执行
在公司实习时遇到一个很奇怪的问题,doInBackground()未及时执行,也就是它并没有在#execute()调用之后马上执行,而是等待了很久才得以执行。 查资料了解到:因为是4.0平台,所以所有 的AsyncTask并不都会运行在单独的线程中,而是被SERIAL_EXECUTOR顺序的使用线程执行。因为我的应用中还有其他地方使用 AsyncTask,所以到网络取图片的AsyncTask也许
安卓开发——AsyncTask内的各个方法调用顺序
AsyncTask内的各个方法调用顺序:  一、首先,用户调用execute方法,启动AsyncTask 。 二、然后在execute方法中: 1、首先调用onPreExecute方法,执行初始化操作。 2、然后从线程池中取出若干个空闲的线程,并使用该线程调用doInBackground方法,执行耗时的操作,如文件下载等。提示:调用execute方法时设置的参数会被直接传递给doInBa
AsyncTask onPostExecute 未执行问题
在android4.0以下设备上onPostExecute不执行,doInBackground也无抛出异常。 在android4.2以上设备上onPostExecute是执行的,没问题。 那么问题就来了,一路查寻,牵扯出好多问题。 以下是我个人遇到的情况,新建个测试AsyncTask项目没有问题,但是在原项目下问题就来了。 AndroidManifest.xml里加入了android:
Activity中获取AsyncTask中onPostExecute的结果返回值
1 创建一个接口import java.util.List;public interface AsyncResponse { void onDataReceivedSuccess(List<String> listData); void onDataReceivedFailed(); }2 在AsyncTask中通过此接口获取到onPostExecute中的数值class Socke
AsyncTask onPostExecute 未执行原因
今天在主界面的Activity里面,通过异步加载后台数据的时候,用到AsyncTask,发现onPostExecute方法一直没有执行,因为这个方法里面可以进行UI的更新,后来才发现,原来是onPostExecute这个方法里面的参数必须和AsyncTask里面定义的一致。 另外,如果还不行,可以试试在onCreate里面加上下面代码。 try {    Class.forName("and