我正在尝试创建自己的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秒钟设置一次assgn1,assgn2等的progressText。但是在onProgressUpdate()期间它不会为progressText设置任何文本,而是在onPostExecute()方法中设置“所有处理”。
如果我在这里错过了什么,有人可以帮我吗?
答案 0 :(得分:1)
在实现自己的AsyncTask
之前,您需要了解一些规则。AsyncTask允许正确且轻松地使用UI线程。这个班 允许您执行后台操作并在 UI线程,而无需操纵线程和/或处理程序。
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";
}
}
注意:我只是提供了一种简单快捷的解决方案,实际上,您需要编写更多代码来处理某些情况,例如处理异常,取消后台任务等。