[英]Android: How to update an UI from AsyncTask if AsyncTask is in a separate class?
我讨厌内部班级。
我有一个主要活动,它启动了一个“短命”的 AsyncTask。
AsyncTask在一个单独的文件中,不是主要活动的内部类
我需要异步任务从主活动更新 textView。
我知道我可以从 onProgressUpdate 更新 TextView,如果 AsyncTask 是一个内部类
但是如何从一个外部的、独立的、异步的任务呢?
更新:这看起来像工作:
在活动中,我将任务称为
backgroundTask = new BackgroundTask(this);
backgroundTask.execute();
在构造函数中我
public BackgroundTask(Activity myContext)
{
debug = (TextView) myContext.findViewById(R.id.debugText);
}
其中 debug 是 AsyncTask 的私有字段。
所以 onProgressUpdate 我可以
debug.append(text);
谢谢大家的建议
AsyncTask 总是与Activity
分开的类,但我怀疑你的意思是它与你的活动类文件在不同的文件中,所以你不能从活动的内部类中受益。 只需将 Activity 上下文作为参数传递给您的异步任务(即传递给它的构造函数)
class MyAsyncTask extends AsyncTask<URL, Integer, Long> {
WeakReference<Activity> mWeakActivity;
public MyAsyncTask(Activity activity) {
mWeakActivity = new WeakReference<Activity>(activity);
}
...
并在需要时使用(记住不要在doInBackground()
期间使用),即当您通常调用时
int id = findViewById(...)
在你调用的 AsyncTask 中,即
Activity activity = mWeakActivity.get();
if (activity != null) {
int id = activity.findViewById(...);
}
请注意,当doInBackground()
正在进行时,我们的Activity
可能会消失(因此返回的引用可能变为null
),但是通过使用WeakReference
我们不会阻止 GC 收集它(并泄漏内存),并且随着 Activity 消失,它通常毫无意义甚至尝试更新它的状态(仍然,根据您的逻辑,您可能想要执行诸如更改内部状态或更新数据库之类的操作,但必须跳过触摸 UI)。
使用接口 1) 创建一个接口
public interface OnDataSendToActivity {
public void sendData(String str);
}
2)在您的活动中实现它
public class MainActivity extends Activity implements OnDataSendToActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
new AsyncTest(this).execute(new String[]{"AnyData"}); // start your task
}
@Override
public void sendData(String str) {
// TODO Auto-generated method stub
}
}
3) 在 AsyncTask(Activity activity){} 中创建构造函数在 AsyncTask 文件中注册您的接口并调用接口方法,如下所示。
public class AsyncTest extends AsyncTask<String, Integer, String> {
OnDataSendToActivity dataSendToActivity;
public AsyncTest(Activity activity){
dataSendToActivity = (OnDataSendToActivity)activity;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dataSendToActivity.sendData(result);
}
}
在这里,您的 OnPostExecute 将在 AsyncTask 完成所有任务后调用,并将获得“结果”作为参数,由 doInBackground(){ return "";} 返回。
而“dataSendToActivity.sendData(result);” 它将调用活动的重写方法“public void sendData(String str) {}”。
要记住的边缘情况:确保将this
传递给AsyncTask
,即您当前活动的上下文,而不是创建活动的另一个实例,否则您的Activity
将被销毁并创建新的Activity
。
在您的活动类中创建一个静态函数,在其中传递上下文以更新您的文本视图,然后在您的 AsynkTask 类中调用此函数进行更新。
在 Activity 类中: public static void updateTextView(){
//你的代码在这里}
在 AynckTask 类中调用这个函数。
只需将上下文(活动或其他)传递给构造函数中的 AsyncTask,然后在 onSuccess 或 onProgressUpdate 中调用上下文中需要的任何内容。
我为这种场景写了一个 AsyncTask 的小扩展。 它允许您将 AsyncTask 保留在单独的类中,但也使您可以方便地访问 Tasks 的完成:
public abstract class ListenableAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result>{
@Override
protected final void onPostExecute(Result result) {
notifyListenerOnPostExecute(result);
}
private AsyncTaskListener<Result> mListener;
public interface AsyncTaskListener<Result>{
public void onPostExecute(Result result);
}
public void listenWith(AsyncTaskListener<Result> l){
mListener = l;
}
private void notifyListenerOnPostExecute(Result result){
if(mListener != null)
mListener.onPostExecute(result);
}
}
所以首先你扩展 ListenableAsyncTask 而不是 AsyncTask。 然后在您的 UI 代码中,创建一个具体实例并设置 listenWith(...)。
这个问题已经得到了回答,我仍然在发布我猜应该如何做..
主要活动类
public class MainActivity extends Activity implements OnClickListener
{
TextView Ctemp;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Ctemp = (TextView) findViewById(R.id.Ctemp);
doConv = (Button) findViewById(R.id.doConv);
doConv.setOnClickListener(this);
}
@Override
public void onClick(View arg0) // The conversion to do
{
new asyncConvert(this).execute();
}
}
现在在异步类中
public class asyncConvert extends AsyncTask<Void, Void, String>
{
SoapPrimitive response = null;
Context context;
public asyncConvert(Context callerclass)
{
contextGUI = callerclass;
}
.
.
.
.
protected void onPostExecute(String result)
{
((MainActivity) contextGUI).Ctemp.setText(result); // changing TextView
}
}
/**
* Background Async Task to Load all product by making HTTP Request
* */
public static class updateTExtviewAsyncTask extends AsyncTask<String, String, String> {
Context context;
ProgressDialog pDialog;
String id, name;
String state_id;
//--- Constructor for getting network id from asking method
public updateTExtviewAsyncTask(Context context,String id,String city)
{
context = context;
state_id = id;
city_name = city;
}
/* *
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute()
{
super.onPreExecute();
pDialog = ProgressDialog.show(context, "","Please wait...", true, true);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args)
{
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
YourClass.UpdateTextViewData("Textview data");
}
}
// 将此代码放在您的活动类中,并声明更新 textview 静态
public static void UpdateTextViewData(String tvData)
{
tv.setText(tvData);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.