自定义异步任务的实现不起作用
Posted
技术标签:
【中文标题】自定义异步任务的实现不起作用【英文标题】:Implementation of custom async task not working 【发布时间】:2019-09-23 07:06:09 【问题描述】:我正在尝试创建自己的 android Asynctask 实现。为此,我创建了一个扩展 Thread 类的抽象类。我声明了 onPreExecute、onPostExecute、onProgressUpdate 和 doInBackground 的方法。
我通过从主线程的 Looper 创建一个处理程序来运行 doInBackground 方法。但是我无法在 onProgressUpdate() 方法中修改 UI 元素,但我可以在 onPostExecute() 方法中修改 UI 元素。
这是我尝试过的。
package com.example.myapplication;
import android.os.Handler;
import android.os.Looper;
public abstract class MyAsyncTask extends Thread
String[] urls;
Handler handler;
abstract protected void onPreExecute();
abstract protected void onPostExecute(String result);
abstract protected void onProgressUpdate(String result);
protected void publishProgress(String progress)
onProgressUpdate(progress);
abstract protected void doInBackground(String... urls);
protected void execute(String... urls)
onPreExecute();
this.urls = urls;
start();
public void run()
try
handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable()
@Override
public void run()
doInBackground(urls);
);
catch (Exception e)
e.printStackTrace();
这是我的 MainActivity。它有进度条和progressText来显示进度。
package com.example.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
ProgressBar bar;
TextView progressText;
LinearLayout container;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bar = findViewById(R.id.progress);
progressText = findViewById(R.id.progressText);
container = findViewById(R.id.container);
public void startProcess(View view)
String[] assignments = "assgn1", "assgn2", "assgn3", "assgn4", "assgn5";
new ProgressAsync().execute(assignments);
public void showProgress()
container.setVisibility(View.VISIBLE);
public void hideProgress()
container.setVisibility(View.GONE);
public class ProgressAsync extends MyAsyncTask
@Override
protected void onPreExecute()
showProgress();
@Override
protected void onPostExecute(String result)
progressText.setText("All processed");
hideProgress();
@Override
protected void onProgressUpdate(String result)
progressText.setText(result + " processed");
@Override
protected void doInBackground(String... urls)
for (int i = 0; i < urls.length; i++)
try
Thread.sleep(2000);
catch (InterruptedException e)
e.printStackTrace();
publishProgress(this.urls[i]);
onPostExecute("SUCCESS");
它应该在每 2 秒后设置 progressText,如 assgn1、assgn2 等。但是它在 onProgressUpdate() 期间没有为 progressText 设置任何文本,而是在 onPostExecute() 方法中设置了“All Processed”。
如果我在这里遗漏了什么,有人可以帮助我吗?
【问题讨论】:
你让MyAsyncTask extends Thread
。线程不是 AsyncTask。你需要MyAsyncTask extends AsyncTask<String, String, String>
@anatoli 我不想创建 AsyncTask 的子类。我想自己实现一个 AsyncTask 版本。
【参考方案1】:
在实现自己的AsyncTask之前,您需要了解一些规则
AsyncTask 允许正确且轻松地使用 UI 线程。这节课 允许您执行后台操作并在 无需操作线程和/或处理程序的 UI 线程。
-
AsyncTask 将产生至少一个后台线程来完成其工作。
doInBackground()
将在这个后台线程上运行,因为如果它在 UI 线程上运行,您的应用将冻结甚至崩溃。
onPreExecute()
、onPostExecute()
、onProgressUpdate()
将在 UI 线程上运行。
在您的代码中,因为 doInBackground()
中的代码在 UI 线程上运行,这就是您的应用冻结的原因,直到它到达 doInBackground()
方法的最后一行。
这是我的解决方案:
MyAsyncTask.java
public abstract class MyAsyncTask extends Thread
private String[] mUrls;
private Handler mMainHandler;
public MyAsyncTask()
// Using this handler to update UI
mMainHandler = new Handler(Looper.getMainLooper());
abstract protected void onPreExecute();
abstract protected void onPostExecute(String result);
abstract protected void onProgressUpdate(String result);
protected void publishProgress(final String progress)
// This will run in UI thread.
mMainHandler.post(new Runnable()
@Override
public void run()
onProgressUpdate(progress);
);
abstract protected String doInBackground(String... urls);
protected void execute(String... urls)
mUrls = urls;
start();
public void run()
// This will run in UI thread.
mMainHandler.post(new Runnable()
@Override
public void run()
onPreExecute();
);
String result = null;
try
// This will run in the background thread.
result = doInBackground(mUrls);
finally
// This will run in UI thread.
final String finalResult = result;
mMainHandler.post(new Runnable()
@Override
public void run()
onPostExecute(finalResult);
);
ProgressAsync.java
public class ProgressAsync extends MyAsyncTask
@Override
protected void onPreExecute()
showProgress();
@Override
protected void onPostExecute(String result)
progressText.setText(result);
hideProgress();
@Override
protected void onProgressUpdate(String result)
progressText.setText(result + " processed");
@Override
protected String doInBackground(String... urls)
for (String url : urls)
publishProgress(url);
try
Thread.sleep(2000);
catch (InterruptedException e)
e.printStackTrace();
return "SUCCESS";
注意:我只是给出了简单快速的解决方案,实际中需要编写更多的代码来处理一些场景,比如处理异常、取消后台任务等。
【讨论】:
感谢 Nhất Giang。现在我知道我错过了什么。以上是关于自定义异步任务的实现不起作用的主要内容,如果未能解决你的问题,请参考以下文章