Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android ProgressBar停止更新_Android_Multithreading_Android Asynctask_Android Ui - Fatal编程技术网

Android ProgressBar停止更新

Android ProgressBar停止更新,android,multithreading,android-asynctask,android-ui,Android,Multithreading,Android Asynctask,Android Ui,我正在尝试解决我的应用程序的UI问题 当进入特定的活动时,应用程序会在目录中查找一些文件,并为每个文件向REST API服务请求一些数据 工作线程实现为一个异步任务: doInBackground方法递归搜索文件夹及其子文件夹中的文件。 如果找到一个文件,一个新的请求将被提交到一个请求队列,该队列由Reformation+OkHTTPClient处理 请求是异步的,Callback函数在检索到文件信息后,会调用执行某些操作的函数,然后调用AsyncTaskpublishProgress() 最后

我正在尝试解决我的应用程序的UI问题

当进入特定的
活动时
,应用程序会在目录中查找一些文件,并为每个文件向REST API服务请求一些数据

工作线程实现为一个
异步任务

doInBackground
方法递归搜索文件夹及其子文件夹中的文件。 如果找到一个文件,一个新的请求将被提交到一个请求队列,该队列由Reformation+OkHTTPClient处理

请求是异步的,
Callback
函数在检索到文件信息后,会调用执行某些操作的函数,然后调用
AsyncTask
publishProgress()

最后调用
onProgressUpdate
来更新
ProgressBar
的当前值和最大值

我遇到的主要问题是,经过一段时间后,
ProgressBar
停止更新,我收到“Choreographer dropped frames”消息,但每次调用
onProgressUpdate
时都会使用更新的值

我认为许多HTTP请求是频繁UI更新的瓶颈

我还尝试创建一个优先级设置为
MAX\u priority
线程,从中调用
publishProgress
,没有区别

我应该遵循哪种模式来提高UI的响应性

下面是一些简化的代码:

异步任务

public class MyAsyncTask implements myCustomListener{
    private int processed = 0;
    private int toProcess = 0;
    private MyCustomActivity mActivity;

    public MyAsyncTask(MyCustomActivity mActivity){
        this.mActivity = mActivity;
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        doScan(mRootDir);
        return null;
    }

    private void doScan(File rootDir){
        for(File file: rootDir.listFiles()){
            if(file.isDirectory()) doScan(file);
            else if(isWantedFile(file)) {
                MyQueues.addRequest(file,this);
                toProcess++;
            }
        }
    }

    @Override
    public void onCustomEventListened(File f){
        //set f as processed
        processed++;
        publishProgress();
    }

    @Override
    protected void onProgressUpdate(Void... voids) {
        if (processed > 1)
            mActivity.showProgressBar(); //If not visible, set visible
        mActivity.updateProgressBar(processed, toProcess);
        Log.i("Scan Progress", processed + "/" + toProcess); //this log print tells me that method is called properly
        if (processed == toProcess) {
            mActivity.hideProgressBar(); //If visible, set not visible
        }
    }

}
public class MyCallback implements Callback<FileInfoClass>{

    private File f;
    private MyCustomListener mListener;

    public MyCallback(File f, MyCustomListener mListener){
        this.f=f;
        this.mListener=mListener;
    }

    @Override
    public void failure(RetrofitError response) {
        mListener.onCustomEventListened(f);
    }

    @Override
    public void success(FileInfoClass fic, Response response) {
        if(check(fic,f)){
            //store fic data...
        }
        mListener.onCustomEventListened(f);
    }
}
请求队列

public class MyQueues{
    private static LinkedBlockingQueue<Runnable> mRequestQueue = new LinkedBlockingQueue<Runnable>();
    private static ThreadPoolExecutor tpe = new ThreadPoolExecutor(4, 4, Long.MAX_VALUE, TimeUnit.NANOSECONDS, mRequestQueue);
    private static OkClient mOkClient;
    private static OkHttpClient mOkHttpClient;

    static{
        if(null==mOkHttpClient){
            File cache = MyApp.getCacheDir();
            HttpResponseCache resCache;
            try {
                resCache = new HttpResponseCache(cache, 10L * 1024 * 1024);
                mOkHttpClient = new OkHttpClient();
                mOkHttpClient.setResponseCache(resCache);
            } catch (IOException e) {
            }
        }
        if(null==mOkClient){
            mOkClient = new OkClient(mOkHttpClient);
        }
    }

    public static interface TheGamesDBService {
        @GET("/getData.php")
        void getData(@Query("id") String id, MyCallback<FileInfoClass> cb);
    }

    private static RestAdapter myAdapter = new RestAdapter.Builder()
            .setClient(mOkClient).setConverter(myConverter())
            .setExecutors(tpe, new MainThreadExecutor())
            .setEndpoint(Constants.MYENDPOINT).build();
    private static MyService mService = myAdapter
            .create(MyService.class);

    public static void addRequest(File f, MyCustomListener mListener) {
            MyCallback cb = new MyCallback(f, mListener);
            myService().getData(f.getName(),cb);
        }
    }

}
公共类MyQueues{
私有静态LinkedBlockingQueue mRequestQueue=新LinkedBlockingQueue();
私有静态ThreadPoolExecutor tpe=新的ThreadPoolExecutor(4,4,Long.MAX_值,TimeUnit.NANOSECONDS,mRequestQueue);
私有静态OkClient-mOkClient;
私有静态Okhttp客户端mokhttp客户端;
静止的{
if(null==mOkHttpClient){
文件缓存=MyApp.getCacheDir();
HttpResponseCache-resCache;
试一试{
resCache=新的HttpResponseCache(缓存,10L*1024*1024);
mOkHttpClient=new-OkHttpClient();
mOkHttpClient.setResponseCache(resCache);
}捕获(IOE异常){
}
}
if(null==mOkClient){
mOkClient=新的OkClient(mOkHttpClient);
}
}
公共静态界面游戏服务{
@获取(“/getData.php”)
void getData(@Query(“id”)字符串id,MyCallback cb);
}
private static RestAdapter myAdapter=new RestAdapter.Builder()
.setClient(mOkClient).setConverter(myConverter())
.setExecutors(tpe,新的MainThreadExecutor())
.setEndpoint(Constants.MYENDPOINT).build();
私有静态MyService mService=myAdapter
.create(MyService.class);
公共静态void addRequest(文件f,MyCustomListener mListener){
MyCallback cb=新的MyCallback(f,mListener);
myService().getData(f.getName(),cb);
}
}
}
MyCallback

public class MyAsyncTask implements myCustomListener{
    private int processed = 0;
    private int toProcess = 0;
    private MyCustomActivity mActivity;

    public MyAsyncTask(MyCustomActivity mActivity){
        this.mActivity = mActivity;
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        doScan(mRootDir);
        return null;
    }

    private void doScan(File rootDir){
        for(File file: rootDir.listFiles()){
            if(file.isDirectory()) doScan(file);
            else if(isWantedFile(file)) {
                MyQueues.addRequest(file,this);
                toProcess++;
            }
        }
    }

    @Override
    public void onCustomEventListened(File f){
        //set f as processed
        processed++;
        publishProgress();
    }

    @Override
    protected void onProgressUpdate(Void... voids) {
        if (processed > 1)
            mActivity.showProgressBar(); //If not visible, set visible
        mActivity.updateProgressBar(processed, toProcess);
        Log.i("Scan Progress", processed + "/" + toProcess); //this log print tells me that method is called properly
        if (processed == toProcess) {
            mActivity.hideProgressBar(); //If visible, set not visible
        }
    }

}
public class MyCallback implements Callback<FileInfoClass>{

    private File f;
    private MyCustomListener mListener;

    public MyCallback(File f, MyCustomListener mListener){
        this.f=f;
        this.mListener=mListener;
    }

    @Override
    public void failure(RetrofitError response) {
        mListener.onCustomEventListened(f);
    }

    @Override
    public void success(FileInfoClass fic, Response response) {
        if(check(fic,f)){
            //store fic data...
        }
        mListener.onCustomEventListened(f);
    }
}
公共类MyCallback实现回调{
私有文件f;
私人MyCustomListener;
公共MyCallback(文件f,MyCustomListener mListener){
这个。f=f;
this.mListener=mListener;
}
@凌驾
公共无效故障(错误响应){
mListener.onCustomEventListened(f);
}
@凌驾
public void成功(FileInfoClass,响应){
如果(检查(fic,f)){
//存储fic数据。。。
}
mListener.onCustomEventListened(f);
}
}

单看这段代码很难对其进行调查,但我看到了潜在的问题

改装回调方法:
failure()
success()
在主线程上被调用,最终
publishProgress()。根据AsyncTask文档,这个方法应该从在专用后台线程上调用的
doInBackground()
方法调用。您应该明确地考虑重构代码。为了更方便地在不同位置打印日志以记录当前线程名称:
thread.currentThread().getName()

此外,我注意到您在
AsyncTask
中保留了对
Activity
的强引用。这是一种非常糟糕的做法。要轻松修复它,请使用
WeakReference
类包装
Activity
引用

如果您决定进行更大的更改,我建议您使用ThreadExecutor将后台操作移动到专用的
服务
,或者使用
IntentService
,它提供现成的排队后台操作。最后,要将进度更改传达给
活动
,请使用
BroadcastReceiver
以及
LocalBroadcastManager

更新


还有一件事要补充。如果您自己在后台处理网络操作,则无需使用改装的回调。这对于直接从UI执行请求很好。相反,同步调用改装请求

你能发布你的代码吗?不幸的是,我不能发布整个代码,因为它很长。如果你告诉我你想看什么部分,我可以发布其中的一些部分。我想看看你在哪里执行改装调用、改装回调、AsyncTask onProgressUpdate以及在哪里使用你的ProgressBar。@Loop抱歉,如果花了这么长时间,我添加了你要求的简化代码。谢谢你宝贵的提示!我按照您的指示编辑了我的代码:我删除了
回调
s以在后台执行整个代码,现在
ProgressBar
已正确更新~6000个请求,但仍然没有滞后的用户界面!