gpt4 book ai didi

multithreading - Android ProgressBar 停止更新

转载 作者:行者123 更新时间:2023-11-30 02:45:48 25 4
gpt4 key购买 nike

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

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

工作线程作为 AsyncTask 实现:

doInBackground 方法递归地搜索文件夹及其子文件夹中的文件。如果找到文件,则会将新请求提交到由 Retrofit+OkHTTPClient 处理的请求队列。

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

onProgressUpdate 最终被调用以更新 ProgressBar 的当前值和最大值。

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

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

我还尝试创建一个优先级设置为 MAX_PRIORITYThread 以从中调用 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 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);
}
}

}

我的回调

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);
}
}

最佳答案

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

Retrofit 回调方法:failure()success() 在主线程上调用,最终在 publishProgress(); 上调用主线程。根据 AsyncTask 文档,此方法应从 doInBackground() 方法调用,该方法在专用后台线程上调用。您绝对应该考虑重构代码。为了更容易在不同的地方打印到 Logcat 当前线程名称:Thread.currentThread().getName()

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

如果您决定进行更大的更改,我建议将后台操作移动到专用的 Service 和 ThreadExecutor 或使用 IntentService 以提供开箱即用的排队后台操作。最后,要将进度更改传达给 Activity,请使用 BroadcastReceiverLocalBroadcastManager

更新

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

关于multithreading - Android ProgressBar 停止更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25077289/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com