Не удается получить доступ к "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
}
}