私は内部のクラスが嫌いです。
「短命」のAsyncTaskを起動するメインアクティビティがあります。
AsyncTaskは個別のファイル内であり、メインアクティビティの内部クラスではありません
メインのアクティビティからtextViewを更新する非同期タスクが必要です。
AsyncTaskが内部クラスの場合、onProgressUpdateからTextViewを更新できることを知っています
しかし、外部の独立した非同期タスクからはどうでしょうか?
更新:これは動作しているように見えます:
Acitivtyでは、タスクを呼び出します
backgroundTask = new BackgroundTask(this);
backgroundTask.execute();
コンストラクターで
public BackgroundTask(Activity myContext)
{
debug = (TextView) myContext.findViewById(R.id.debugText);
}
debugはAsyncTaskのプライベートフィールドでした。
だからonProgressUpdate私はできる
debug.append(text);
あなたのすべての提案をありがとう
[〜#〜] edit [〜#〜]WeakReference
を使用するように回答を編集しました
AsyncTaskは常に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(...);
}
_
Activity
はdoInBackground()
の進行中に削除できることに注意してください(したがって、返される参照はnull
になります)が、WeakReference
を使用することにより、 GCがそれを収集(およびメモリリーク)するのを防ぎ、Activityがなくなると、通常、その状態を更新しようとしても意味がありません(それでも、ロジックに応じて、内部状態の変更やDBの更新などの操作を行い、UIに触れることもできます)スキップする必要があります)。
インターフェイスの使用1)インターフェイスを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 "";}によって返されるパラメーターとして「結果」を取得します。
While "dataSendToActivity.sendData(result);"アクティビティのオーバーライドされたメソッド「public void sendData(String str){}」を呼び出します。
覚えておくべきエッジケース:this
を渡すようにしてください。つまり、現在のアクティビティのコンテキストをAsyncTask
に渡し、アクティビティの別のインスタンスを作成しないでください。そうしないと、Activity
新しいものが作成されます。
テキストビューを更新するためにコンテキストを渡すアクティビティクラスで静的関数を作成し、AsynkTaskクラスでこの関数を呼び出して更新します。
Activityクラス内:public static void updateTextView(){
//ここにコード}
AynckTaskクラスでこの関数を呼び出します。
コンテキスト(アクティビティなど)をコンストラクターでAsyncTaskに渡し、onSuccessまたはonProgressUpdateでコンテキストに必要なものを呼び出します。
この種のシナリオのために、AsyncTaskの小さな拡張機能を作成しました。 AsyncTaskを別のクラスに保持することができますが、タスクの完了への便利なアクセスも提供します。
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);
}
}
したがって、最初にAsyncTaskの代わりにListenableAsyncTaskを拡張します。次に、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 staticの更新も宣言します
public static void UpdateTextViewData(String tvData)
{
tv.setText(tvData);
}