Не удается получить доступ к "findViewById" в AsyncTask

Я использую класс AsyncTask для загрузки данных из файла php. После загрузки я хочу поместить эти данные в разные текстовые элементы, но я не могу использовать метод 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);

Но не работает тоже.

Обратите внимание, что я вызываю эту 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;
}


}

Что мне делать?

Спасибо.

Ответ 1

Передайте свой завышенный вид в 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();

Ответ 2

попробуйте как передать 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..

Ответ 3

Просто добавьте дополнительный параметр в свою AsyncTask с представлением myFragmentView и найдите текст на нем.

@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);

Ответ 4

Вы можете сделать свой myFragmentView глобальным, таким образом, вы можете получить доступ к вашим представлениям из любого места, даже из ваших методов фрагмента, таких как onStart().

Ответ 5

Попробуйте это ((Activity)context) это работает для меня...

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

Ответ 6

Сделайте свой AsyncTask независимым от Activity

Что если ваш AsyncTask является отдельным классом Java, но вы все равно хотите получить доступ к элементам View из Activity из AsyncTask.

Вы можете использовать интерфейс

Преимущество?

Если вы хотите использовать один и тот же AsyncTask с различными действиями, тогда интерфейсный подход является лучшим, поскольку ваш AsyncTask можно использовать с любым действием, даже не меняя код в 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+"");      
    }

}

Будущее

Вы не сможете осознать всю прелесть своего кода, пока не будете использовать AsyncTask в какой-либо другой деятельности.
Допустим, в будущем вы захотите использовать эту AsyncTask в некотором другом AsyncTask которое показывает прогресс в Spinner.
Как вы будете использовать это? Просто! реализовать интерфейс и переопределить метод.

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       
    }

}