簡體   English   中英

無法在 AsyncTask 中訪問“findViewById”

[英]Can't access “findViewById” in AsyncTask

我正在使用 AsyncTask 類從 php 文件下載數據。 下載后,我想把這些數據,放到不同的TextViews中,但是我不能使用findViewById這個方法。

問題是我是通過單獨的類來做這件事的,而且這一切都在一個片段中。

這是我的代碼:

public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
private Context mContext;
[...]
public RecuperarComentarisFoto(Context context){
    this.mContext=context;
}
@Override
protected void onPreExecute() {
    [...]
}

@Override
protected String doInBackground(String... arg0) { 
    params.add(new BasicNameValuePair("pid", "1"));
    JSONObject json = jsonParser.makeHttpRequest(url_get_comentaris, "GET", params);
    JSONArray productObj;
    //HERE I RETRIEVE DATA FROM JSON. ITS WORKING OK.

    return null;
}

我的問題在哪里:

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    this.pDialog.dismiss();
    TextView comentariEditText = (TextView) findViewById(R.id.commentsMostrar);
}

我試過這個:

        TextView comentariEditText = (TextView) mContext.findViewById(R.id.commentsMostrar);

但也不起作用。

請注意,我從 Fragment 調用此 AsyncTask。 如您所見,我必須將 getActivity() 檢索到的上下文傳遞給 AsyncTask:

public class MyFragmentA extends Fragment {
Context cont;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);

    cont=getActivity();
    new RecuperarComentarisFoto(cont).execute();
    return myFragmentView;
}


}

我應該怎么辦?

謝謝你。

像這樣將膨脹的視圖傳遞給 AsyncTask:

public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
private Context mContext;
private View rootView;
[...]
public RecuperarComentarisFoto(Context context, View rootView){
    this.mContext=context;
    this.rootView=rootView;
}
@Override
protected void onPreExecute() {
    [...]
}

@Override
protected String doInBackground(String... arg0) { 
    params.add(new BasicNameValuePair("pid", "1"));
    JSONObject json = jsonParser.makeHttpRequest(url_get_comentaris, "GET", params);
    JSONArray productObj;
    //HERE I RETRIEVE DATA FROM JSON. ITS WORKING OK.

    return null;
}
@Override
protected void onPostExecute(String result) {
    //super.onPostExecute(result);  <--GET RID OF THIS (it will screw up on 2.1 devices)
    this.pDialog.dismiss();
    // use rootview to findViewById
    TextView comentariEditText = (TextView) rootView.findViewById(R.id.commentsMostrar);
}

然后像這樣打電話,

View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);

cont=getActivity();
new RecuperarComentarisFoto(cont, myFragmentView).execute();

試試這個((Activity)context)它對我有用......

TextView comentariEditText = 
(TextView) ((Activity)context).findViewById(R.id.commentsMostrar);

使您的 AsyncTask 獨立於 Activity

如果

  • 您的AsyncTask是一個單獨的 Java 類(在 Activity 之外) ,您仍然希望從AsyncTask訪問任何Activity的 View 元素。
  • 你想重用你AsyncTask與其他一些活動,而不在您的更改任何代碼AsyncTask

答案是 使用接口

優勢?
接口使事物獨立(松散耦合)

您可以按照以下步驟操作:

1)創建接口

public interface AsyncTaskListener{

   public void giveProgress(int progress);

}

2)在你的 AsyncTask 中使用監聽器

 DownloadSongTask extends AsyncTask<String,Integer,Void>{

    private AsyncTaskListener listener;

    public DownloadSongTask(Context context)
    {
        listener= (AsyncTaskListener)context;    // Typecast 
    }

    @Override
    public void doInbackGround(String... params)
    {
         // Download code
         int downloadPerc = // calculate that
         publish(downloadPerc);   
    }

    @Override
    public void onProgressUpdate(Integer... params)
    {
         listener.giveProgress(params[0]);  // Use it 
    }

}

3)在Activity和Override方法中實現接口

 public class YourActivity extends AppcompatActivity implements AsyncTaskListener{

    private TextView textView;

    // Activity code //
    new  DownloadSongTask(this).execute("Paradise.mp3");  // this is how you start Task

    @Override 
    public void giveProgress(int progress){
       textView.setText(progress+"");      
    }

}

未來

除非您必須在其他活動中使用 Your AsyncTask,否則您不會意識到代碼的美妙之處。
假設將來您想在一些顯示 Spinner 進度的其他活動中使用此AsyncTask
你將如何使用它? 簡單的! 實現接口並覆蓋方法。

public class YourActivity extends AppcompatActivity implements AsyncTaskListener{

     private Spinner spinner;

     // Activity code //
     new  DownloadSongTask(this).execute("Paradise.mp3");  // this is how you start Task

    @Override 
    public void giveProgress(int progress){
       // Your Spinner code       
    }

}

在傳遞MyFragmentA上下文而不是getActivity()之后嘗試:

 cont=this;
 new RecuperarComentarisFoto(cont).execute();

並將RecuperarComentarisFoto更改為

public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
public Fragment mContext;
[...]
public RecuperarComentarisFoto(Fragment context){
    this.mContext=context;
}
@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    this.pDialog.dismiss();
    TextView comentariEditText = 
                    (TextView)mContext.findViewById(R.id.commentsMostrar);
}
//...your code..

只需使用視圖 myFragmentView 向您的 AsyncTask 添加一個額外的參數,然后在其上找到您的文本視圖。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);

    cont=getActivity();
    new RecuperarComentarisFoto(cont, myFragmentView).execute();
    return myFragmentView;
}

然后只需使用該視圖..

TextView comentariEditText = (TextView) mView.findViewById(R.id.commentsMostrar);

您可以將myFragmentView全局,這樣您就可以從任何地方訪問您的視圖,甚至可以從onStart()等片段方法訪問您的視圖。

使用RecuperarComentarisFoto(Context context, View rootView)的公認答案給了我以下信息:

java\MyFragmentA.java:64: error: constructor RecuperarComentarisFoto in class RecuperarComentarisFoto cannot be applied to given types;
                new RecuperarComentarisFoto(cont, myFragmentView).execute();
                ^
  required: no arguments
  found: MyFragmentA,View
  reason: actual and formal argument lists differ in length

不知道為什么結果和上面的提議不一樣。 我使用了 API 版本 24。

因此我在AsyncTask使用了一個額外的方法initialize()

public class RecuperarComentarisFoto extends AsyncTask<String, String, String>{
    private Context mContext;
    private View rootView;
    ...
    public initialize(Context context, View rootView){
        this.mContext=context;
        this.rootView=rootView;
    }
    ...
}

在調用 MyFragmentA 類的內部:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ...
        View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
        cont=getActivity();

        RecuperarComentarisFoto rcf = new RecuperarComentarisFoto();
        rcf.initialize(cont, myFragmentViewt);
        rcf.execute(this);
        ...
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM