自定义异步任务的实现不起作用
Implementation of custom async task not working
我正在尝试创建自己的 android Asynctask 实现。为此,我创建了一个抽象 class,它扩展了 Thread class。我为 onPreExecute、onPostExecute、onProgressUpdate 和 doInBackground 声明了方法。
我是 运行 doInBackground 方法,通过从主线程的 Looper 创建一个处理程序。但是我无法修改 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" 。
如果我在这里遗漏了什么,有人可以帮助我吗?
在实施您自己的规则之前,您需要了解一些规则 AsyncTask
AsyncTask enables proper and easy use of the UI thread. This class
allows you to perform background operations and publish results on the
UI thread without having to manipulate threads and/or handlers.
- AsyncTask 将产生至少一个后台线程来完成它的工作。
doInBackground()
将在此后台线程上 运行,因为如果它 运行 在 UI 线程上,您的应用程序将冻结甚至崩溃。
onPreExecute()
、onPostExecute()
、onProgressUpdate()
将在 UI 线程上 运行。
在您的代码中,因为 doInBackground()
运行 中的代码在 UI 线程上,所以您的应用会冻结,直到它到达 [=12= 中的最后一行]方法。
这是我的解决方案:
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";
}
}
注意:我只是给出了简单快捷的解决方案,实际中,你需要写更多的代码来处理一些场景,比如处理异常,取消后台任务,等等
我正在尝试创建自己的 android Asynctask 实现。为此,我创建了一个抽象 class,它扩展了 Thread class。我为 onPreExecute、onPostExecute、onProgressUpdate 和 doInBackground 声明了方法。
我是 运行 doInBackground 方法,通过从主线程的 Looper 创建一个处理程序。但是我无法修改 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" 。
如果我在这里遗漏了什么,有人可以帮助我吗?
在实施您自己的规则之前,您需要了解一些规则 AsyncTask
AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
- AsyncTask 将产生至少一个后台线程来完成它的工作。
doInBackground()
将在此后台线程上 运行,因为如果它 运行 在 UI 线程上,您的应用程序将冻结甚至崩溃。onPreExecute()
、onPostExecute()
、onProgressUpdate()
将在 UI 线程上 运行。
在您的代码中,因为 doInBackground()
运行 中的代码在 UI 线程上,所以您的应用会冻结,直到它到达 [=12= 中的最后一行]方法。
这是我的解决方案:
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";
}
}
注意:我只是给出了简单快捷的解决方案,实际中,你需要写更多的代码来处理一些场景,比如处理异常,取消后台任务,等等