I would like to run an Activity from onPostExecute().
So I followed the answers to this post : Android AsyncTask: start new Activity in onPostExecute()
But it does not work for me ...
MyAsyncActivity :
public class AsyncGetUsersActivity extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params) {
String inputLine = null;
try {
URL url = new URL(Config.HOST "/list/users"); // My URL
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
inputLine = in.readLine(); // Get my data
in.close();
}
catch (Exception e)
{
Log.i("pls", "error : " e.toString());
e.printStackTrace();
}
return inputLine;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Intent intent = new Intent(AsyncGetUsersActivity.this, SelectAccountActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
}
}
I get 2 errors :
1 : Cannot resolve constructor 'Intent(com.example.booklist.AsyncGetUsersActivity, java.lang.Class<com.example.booklist.SelectAccountActivity>)'
From :
Intent intent = new Intent(AsyncGetUsersActivity.this, SelectAccountActivity.class);
2 : Cannot resolve method 'getApplicationContext' in 'AsyncGetUsersActivity'
From :
getApplicationContext().startActivity(intent);
How can I make it work ?
CodePudding user response:
Ok, several things here. First the main error: you named the class AsyncGetUsersActivity but it's not an Activity. It doesn't derive from Activity or one of its subclasses. As such, it isn't an Activity. So it doesn't have a getApplicationContext function and can't be passed as the first parameter to an Intent constructor. (side note: if it was an activity you could have get passed this
rather than call getApplicationContext at all)
Secondly- AsyncTask is deprecated. There's issues with them, you probably shouldn't be using them unless you know what you're doing. And while you'll see a lot of examples of it, they really shouldn't be used for networking at all (network calls can take a long time and will hold up all other AsyncTasks until its finished).
Third- I'd really suggest using retrofit for network IO. This isn't a bug in your code, what you did looks more or less ok, although you're not actually using the result of your network call in any way. But Retrofit will handle all the threading for you.
CodePudding user response:
Caveats about using an AsyncTask aside (it's deprecated, prone to memory leaks, and only runs serially on a single thread by default), the solution to your case is to pass a context in to the class to use where you need it.
Launching an activity requires a Context, which you do not have in your AsyncTask class (and as a side note, naming your class AsyncGetUsersActivity
is confusing since the class is not an Activity - that's why you can't use it like one). The example you followed probably defined the AsyncTask as a nested inner class inside an Activity, which let them call methods on the Activity, but this can cause memory leaks.
If you want to do things requiring a context, you can pass one in at construction, like this:
public class DemoAsyncTask extends AsyncTask<String, String, String> {
private final WeakReference<Context> context;
DemoAsyncTask(Context c) {
context = new WeakReference<>(c);
}
@Override
protected String doInBackground(String... params) {
String inputLine = null;
// ...
return inputLine;
}
@Override
protected void onPostExecute(String s) {
Context ctx = context.get();
if( ctx == null ) return;
Intent intent = new Intent(ctx, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
}
}
Then you would create from some Activity like this (passing in this
as the Context for it to use)
DemoAsyncTask task = new DemoAsyncTask(this);
task.execute("my arg");