Android:如果 AsyncTask 在单独的类中,如何从 AsyncTask 更新 UI?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12252654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: How to update an UI from AsyncTask if AsyncTask is in a separate class?
提问by realtebo
I hate inner class.
我讨厌内部班级。
I've a main activity who launches a 'short-life' AsyncTask.
我有一个主要活动,它启动了一个“短命”的 AsyncTask。
AsyncTask is in a separate file, is not an inner class of main activity
AsyncTask在一个单独的文件中,不是主要活动的内部类
I need async task updates a textView from main Activity.
我需要异步任务从主活动更新 textView。
I know i can update a TextView from onProgressUpdate, if AsyncTask is a inner class
我知道我可以从 onProgressUpdate 更新 TextView,如果 AsyncTask 是一个内部类
But how from an external, indipendent, async task ?
但是如何从一个外部的、独立的、异步的任务呢?
UPDATE: This looks like working :
更新:这看起来像工作:
In acitivty i call the task
在活动中,我将任务称为
backgroundTask = new BackgroundTask(this);
backgroundTask.execute();
In the constructor i've
在构造函数中我
public BackgroundTask(Activity myContext)
{
debug = (TextView) myContext.findViewById(R.id.debugText);
}
where debug was a private field of AsyncTask.
其中 debug 是 AsyncTask 的私有字段。
So onProgressUpdate I can
所以 onProgressUpdate 我可以
debug.append(text);
Thanks for all of you suggestions
谢谢大家的建议
回答by Marcin Orlowski
AsyncTask is always separate class from Activity
, but I suspect you mean it is in different file than your activity class file, so you cannot benefit from being activity's inner class. Simply pass Activity context as argument to your Async Task (i.e. to its constructor)
AsyncTask 总是与 分开的类Activity
,但我怀疑你的意思是它与你的活动类文件在不同的文件中,所以你不能从活动的内部类中受益。只需将 Activity 上下文作为参数传递给您的异步任务(即传递给它的构造函数)
class MyAsyncTask extends AsyncTask<URL, Integer, Long> {
WeakReference<Activity> mWeakActivity;
public MyAsyncTask(Activity activity) {
mWeakActivity = new WeakReference<Activity>(activity);
}
...
and use when you need it (remember to NOT use in during doInBackground()
) i.e. so when you would normally call
并在您需要时使用(记住不要在期间使用doInBackground()
),即当您通常会打电话时
int id = findViewById(...)
in AsyncTask you call i.e.
在你调用的 AsyncTask 中,即
Activity activity = mWeakActivity.get();
if (activity != null) {
int id = activity.findViewById(...);
}
Note that our Activity
can be gone while doInBackground()
is in progress (so the reference returned can become null
), but by using WeakReference
we do not prevent GC from collecting it (and leaking memory) and as Activity is gone, it's usually pointless to even try to update it state (still, depending on your logic you may want to do something like changing internal state or update DB, but touching UI must be skipped).
请注意,我们Activity
可以在进行doInBackground()
中时消失(因此返回的引用可以变为null
),但是通过使用WeakReference
我们并不能阻止 GC 收集它(和泄漏内存),并且随着 Activity 消失,即使尝试更新它通常也毫无意义状态(仍然,根据您的逻辑,您可能想要执行诸如更改内部状态或更新数据库之类的操作,但必须跳过触摸 UI)。
回答by Ams
Using Interface 1) Create one Interface
使用接口 1) 创建一个接口
public interface OnDataSendToActivity {
public void sendData(String str);
}
2) Implements it in your Activity
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) Create constructor in AsyncTask(Activity activity){} Register your Interface in AsyncTask file and call interface method as below.
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);
}
}
Here, your OnPostExecute will call after all task done by AsyncTask and will get "result" as a parameter, returned by doInBackground(){ return "";}.
在这里,您的 OnPostExecute 将在 AsyncTask 完成所有任务后调用,并将获得“结果”作为参数,由 doInBackground(){ return "";} 返回。
While "dataSendToActivity.sendData(result);" it will call activity's overrided method "public void sendData(String str) {}".
而“dataSendToActivity.sendData(result);” 它将调用活动的重写方法“public void sendData(String str) {}”。
An edge case to remember: Be sure to pass this
, i.e. you current activity's context to AsyncTask
and not create another instance of your activity, otherwise your Activity
will be destroyed and new one is created.
要记住的边缘情况:确保将this
,即您当前活动的上下文传递给AsyncTask
而不是创建您的活动的另一个实例,否则您的活动Activity
将被销毁并创建新的实例。
回答by pyus13
Make an static function in your activity class passing context in it to update your text view and then call this function in your AsynkTask class to update.
在您的活动类中创建一个静态函数,在其中传递上下文以更新您的文本视图,然后在您的 AsynkTask 类中调用此函数进行更新。
In Activity class: public static void updateTextView(){
在 Activity 类中: public static void updateTextView(){
//your code here }
//你的代码在这里}
In AynckTask class call this function.
在 AynckTask 类中调用这个函数。
回答by newbyca
I wrote a small extension to AsyncTask for this kind of scenario. It allows you to keep your AsyncTask in a separate class, but also gives you convenient access to the Tasks's completion:
我为这种场景写了一个 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);
}
}
So first you extend ListenableAsyncTask instead of AsyncTask. Then in your UI code, make a concrete instance and set listenWith(...).
所以首先你扩展 ListenableAsyncTask 而不是 AsyncTask。然后在您的 UI 代码中,创建一个具体实例并设置 listenWith(...)。
回答by Manfred Moser
Just pass the context (activity or whatever) to your AsyncTask in a constructor and then in onSuccess or onProgressUpdate call whatever you need on the context.
只需将上下文(活动或其他)传递给构造函数中的 AsyncTask,然后在 onSuccess 或 onProgressUpdate 中调用上下文中需要的任何内容。
回答by Sujal Mandal
The Question has already been answered, still im posting how it should be done i guess..
这个问题已经得到了回答,我仍然在发布我猜应该如何做..
Mainactivity class
主要活动类
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();
}
}
now in the async class
现在在异步类中
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
}
}
回答by Lucky Rana
/**
* 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");
}
}
// place this code inside your activity class and also declare updating textview static
// 将此代码放在您的活动类中,并声明更新 textview 静态
public static void UpdateTextViewData(String tvData)
{
tv.setText(tvData);
}