Can't access "findViewById" in AsyncTask
I'm using an AsyncTask class to download data from a php file. After downloading, I want to put this data, into different TextViews, but I can't use the method findViewById.
The problem, is that I'm doing this by separate classes, and it all within a fragment.
This is my code:
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;
}
And where I've the problem:
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
this.pDialog.dismiss();
TextView comentariEditText = (TextView) findViewById(R.id.commentsMostrar);
}
I've tried this:
TextView comentariEditText = (TextView) mContext.findViewById(R.id.commentsMostrar);
But isn't working too.
Note that I'm calling this AsyncTask from a Fragment. As you can see, I had to pass the context retrieved by getActivity() to the 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;
}
}
What should I do?
Thank you.
Solution 1:
Pass your inflated view to the AsyncTask like this :
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);
}
Then call like so,
View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
cont=getActivity();
new RecuperarComentarisFoto(cont, myFragmentView).execute();
Solution 2:
Try this ((Activity)context)
it works for me...
TextView comentariEditText =
(TextView) ((Activity)context).findViewById(R.id.commentsMostrar);
Solution 3:
Make your AsyncTask independent of Activity
What if
- Your
AsyncTask
is a seperate Java class (Outside of Activity) and you still want to access the View elements of anyActivity
fromAsyncTask
. - You want to reuse your
AsyncTask
with some other Activity without any code change in the yourAsyncTask
Answer is. Use an interface
Advantage?
An interface makes things independent (loosely coupled)
You can follow these steps:
1) Create an interface
public interface AsyncTaskListener{
public void giveProgress(int progress);
}
2) Use listener in your 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) Implement the interface in the Activity and Override method
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+"");
}
}
Future
You will not realize the beauty of your code until you have to use Your AsyncTask in some other Activity.
Lets say in future you want to use this AsyncTask
in some Other Activity which shows progress in a Spinner.
How will you use it ?
Simple! implement the interface and override the method.
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
}
}
Solution 4:
try as after passing MyFragmentA
context instead of getActivity()
:
cont=this;
new RecuperarComentarisFoto(cont).execute();
and change RecuperarComentarisFoto
as
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..
Solution 5:
Just add a extra parameter to your AsyncTask with the view myFragmentView and find your textview on that.
@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;
}
and then just use that view..
TextView comentariEditText = (TextView) mView.findViewById(R.id.commentsMostrar);