Reputation: 5506
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.
Upvotes: 12
Views: 21511
Reputation: 870
The accepted answer with use of RecuperarComentarisFoto(Context context, View rootView)
gives me the message:
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
I don't know why the result is different from the proposal above. I used API version 24.
Therefore I use an additional method initialize()
inside the AsyncTask
:
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;
}
...
}
And inside of the calling MyFragmentA class:
@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);
...
}
Upvotes: 0
Reputation: 18202
What if
AsyncTask
is a seperate Java class (Outside of Activity)
and you still want to access the View elements of any Activity
from
AsyncTask
.AsyncTask
with some other Activity without
any code change in the your AsyncTask
Answer is. Use an interface
Advantage?
An interface makes things independent (loosely coupled)
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+"");
}
}
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
}
}
Upvotes: 3
Reputation: 406
Try this ((Activity)context)
it works for me...
TextView comentariEditText =
(TextView) ((Activity)context).findViewById(R.id.commentsMostrar);
Upvotes: 3
Reputation: 63
You can make your myFragmentView
global, this way you can access your views from anywhere even from your fragment methods like onStart()
.
Upvotes: 0
Reputation: 17140
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();
Upvotes: 28
Reputation: 101
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);
Upvotes: 1
Reputation: 132972
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..
Upvotes: 2