I have one task that execute the method doInBackground and return a boolean value. What I want is to initiate a new Intent but the method startActivity is not available. How can I do that?
My task:
public class LoginTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
boolean sucess;
//do some stuff
return sucess;
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
//startActivity(new Intent(this, MainViewActivity.class));
//it doesn't find startActivity
}
}
}
Pass the Activity that starts the AsyncTak in the constructor
public class LoginTask {
private Context mCtx;
public LoginTask(Context ctx){
mCtx = ctx;
}
....
#Override
protected void onPostExecute(Boolean result) {
if (result) {
mCtx.startActivity(new Intent(mCtx, MainViewActivity.class));
}
}
}
A remark about previous replies:
Please remember to do not leak your activity. Use WeakReference class:
public static class LoginTask extends AsyncTask<String, Integer, Boolean> {
WeakReference<Activity> mActivityReference;
public LoginTask(Activity activity){
this.mActivityReference = new WeakReference<Activity>(activity);
}
#Override
protected Boolean doInBackground(String... params) {
boolean sucess;
//do some stuff
return sucess;
}
#Override
protected void onPostExecute(Boolean result) {
if (result && mActivityReference.get() != null) {
Activity activity = mActivityReference.get();
activity.startActivity(new Intent(activity, MainViewActivity.class));
}
}
}
You need to create the task with a reference to the activity or context that spawned it.
public class LoginTask extends AsyncTask<String, Integer, Boolean> {
Activity mActivity;
public LoginTask(Activity activity){
this.mActivity = mActivity;
}
#Override
protected Boolean doInBackground(String... params) {
boolean sucess;
//do some stuff
return sucess;
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
mActivity.startActivity(new Intent(mContext, MainViewActivity.class));
}
}
}
Are you sure that startActivity is not available? I just tested it and it works fine for me.
I think you should replace the this in your line, because the this doesn't refer to the Activity, it refers to the ASyncTask.
startActivity(new Intent(getApplicationContext(), MainViewActivity.class));
That should work.
this inside onPostExecute() refers to AsyncTask class instance.
Use YourActivityName.this instead:
startActivity(new Intent(ParentActivity.this, MainViewActivity.class));
Related
I would need some help to figure out how to return a doInBackground() value in AsyncTask which code is an interface. Here is an example
private class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
public MyAsyncTask() {
super();
// do stuff
}
#Override
protected Boolean doInBackground(Void... void) {
checkIfContentAvailable(new interfaceMediaAvailableToDownload() {
#Override
public void onComplete(boolean resutl) {
return result; //This must be doInBackground return value, not onSuccess which is Void
}
#Override
public void onInternetError() {
return false; //This must be doInBackground return value, not onSuccess which is Void
}
};
}
#Override
protected void onPostExecute(Boolean result) {
if (result){
//Do stuff
}else{
//Do stuff
}
}
}
Obviously, this above code can't work because I don't know how to return onSuccess() value to doInBackground().
I hope this is clear enough....
EDIT
Okay my bad, I thought it would have been more readable to hide MyInterface usage, but I realize through your answers it is not. So I completed the code to add more details.
Any idea please?
Thank you in advance.
Create the object of the Mynterface in the place where you execute the AsyncTask.
Create a object reference of the MyInterface inside the AsyncTask ans set your interface object.
Then call the onSuccess method like below
`
private class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
MyInteface myInterface;
setMyInterface(MyInterface interface){this.myInterface = interface;}
public MyAsyncTask() {
super();
// do stuff
}
#Override
protected Boolean doInBackground(Void... void) {
this.myInterface.onSuccess(); // or call on failure if failure happened
}
#Override
protected void onPostExecute(Boolean result) {
//Do stuff with result
}
}
`
Use it like ...
MyAsyncTask async = new MyAsyncTask();
async.setMyInterface(this);
async.execute();
Implement the interface in the place where your are executing.
This how you can do it.
I have an IME service class and a long operation method in it. I want to run the LongOperation task in a asyncTask class that is in the IME Service class.
public class Myimeservice extends InputMethodService
implements KeyboardView.OnKeyboardActionListene {
//...
//some code here....
//...
public void setDictionary(){
//....
}
private class LongOperation extends AsyncTask<String, Void, String> {
private Myimeservice parent;
public LongOperation(Myimeservice pim){
parent = pim;
}
#Override
protected String doInBackground(String... params) {
Myimeservice tmp = new Myimeservice();
tmp.setDictionary();
return "Executed";
}
#Override
protected void onPostExecute(String result) {
//app.hideLoading();
}
#Override
protected void onPreExecute() {
//app.showLoading();
}
#Override
protected void onProgressUpdate(Void... values) {}
}
When i run it, the application forced to close. please help me.
I think the error is somewhere in your public void setDictionary() method.
I assume that you are manipulating a variable that is bound to the UIThread/MainThread, the application will crash since doInBackground is on another Thread.
Instead make the setDictionary() method return the dictionary and return it instead of "Executed" in doInBackground().
This will call the onPostExecute(Object result) which is run on UIThread/MainThread.
Something like this:
private class LongOperation extends AsyncTask<String, Void, Dictionary> {
#Override
protected Dictionary doInBackground(String... params) {
Myimeservice tmp = new Myimeservice();
Dictionary dict = tmp.setDictionary();
return dict;
}
#Override
protected void onPostExecute(Dictionary result) {
//do what ever you meant to do with it;
}
}
If you are not expecting any result from it you can just do:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
tmp.setDictionary();
}
});
I use the Runnable instead of AsyncTask and the problem solved.
final Runnable r = new Runnable(){
public void run(){
setDictionary();
}
};
this code is in onCreate() method of service.
Tanks a lot Tristan Richard.
Trying to call MainActivity method on onPostExecute(), but not getting any success. I tried so many things, but I think I am doing something wrong. processFinish() method on MainActivity is not called from onPostExecute().
//myClass.java
public class myClass extends Activity {
public AsyncResponse delegate=null;
public myClass(Context context){
this.mContext = context;
}
public interface AsyncResponse {
void processFinish(String output);
}
public class GetNotification extends AsyncTask<Integer, Void, String>{
public GetNotification() {
super();
}
#Override
protected String doInBackground(Integer... mArgs){
//code
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
delegate.processFinish(result);
}
#Override
protected void onPreExecute(){
}
}
public void getValue(int f){
m_flag = f;
if(Build.VERSION.SDK_INT >= 11){
new GetNotification().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, f);
}
else{
new GetNotification().execute(f);
}
}
}
//MainActivity.java
public class MainActivity extends Activity implements AsyncResponse{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//code
}
#Override
public void processFinish(String output){
getComActivity(output);
}
private void getData(String mURL){
this.getUrl=new com.sample.myClass(this);
getUrl.getValue(1);
}
public void getComActivity(String gStr){
if (gStr != null && gStr.trim() != ""){
Intent mIntent = new Intent(this.getApplicationContext(), myActivity.class);
this.startActivity(mIntent);
}
}
}
You need to initialze delegate. Change the code in myClass constructor.
public myClass(Context context){
delegate = (AsyncResponse) context;
}
public GetNotification() {
super();
}
//In your AsyncTask class
//use MainActivity or myClass instead of Activity
private Activity activity;
public GetNotification(Activity activity) {
this.activity = activity;
}
private void callMethod()
{
activity.some_method();
}
public class myClass extends Activity {
public AsyncResponse delegate=null;
Context mContext;
public myClass(Context context){
this.mContext = context;
}
public interface AsyncResponse {
void processFinish(String output);
}
public class GetNotification extends AsyncTask<Integer, Void, String>{
public GetNotification() {
super();
}
#Override
protected void onPreExecute(){
//start dialog progress over here
}
#Override
protected String doInBackground(Integer... mArgs){
//code
return null;
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
delegate.processFinish(result);
}
}
#SuppressLint("NewApi")
public void getValue(int f){
int m_flag = f;
if(Build.VERSION.SDK_INT >= 11){
new GetNotification().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, f);
}
else{
new GetNotification().execute(f);
if( MainActivity.activity!=null)
MainActivity.getComActivity("PassYourStringOverHere"); //here I am giving example how to call MainActivity method from other activity
}
}
public class MainActivity extends Activity implements AsyncResponse{
private myClass getUrl;
public static Activity activity=null;
public static Context context=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity=this;//use to initialize the activity...later you can call...and start intent using this activity object...
context=this;//use for Intent...why I used this pattern because i made a static method so I have to do...or else it will show error...
//code
}
#Override
public void processFinish(String output){
getComActivity(output);
}
private void getData(String mURL){
this.getUrl=new com.sample.myClass(this);
getUrl.getValue(1);
}
public static void getComActivity(String gStr){
if (gStr != null && gStr.trim() != ""){
Intent mIntent = new Intent(context, myActivity.class);
activity.startActivity(mIntent);
}
}
}
My calling activity:
public class Hello extends Activity {
public void onCreate(Bundle savedInstanceState) {
MyTask mt = new MyTask(this);
mt.execute();
}
Now In MyTask (an external class):
public class MyTask extends AsyncTask<Void, Void, Void> {
private Context mContext;
public MyTask(Context context) {
mContext = context;
}
//doinbackground, etc
protected void onPostExecute() {
mContext.finish();
}
Other things are working as expected if I remove mContext.finish() above.
But if I'm calling mContext.finish() , I'm getting an error: The method finish() is undefined for the type Context (Eclipse doesn't show finish() when I write mContext. so that suggests I'm using finish() wrongly.)
What do I need to do to finish the calling activity Hello after MyTask completes the task
((Activity)mContext).finish();
Would be the correct way to cast a Context to an Activity and call its finish() method. Not sure why you'd want to finish an Activity from an AsyncTask though
What you can try to do instead of calling context.finish(), why don't you do a callback interface like this:
public interface TaskCallback{
void done();
}
Then you implement this into your Activity
public Hello extends Activity implements TaskCallback{
.....BUNCH OF ACTIVITY CODE.....
public void onCreate(Bundle savedInstanceState) {
MyTask mt = new MyTask(this);
mt.execute();
}
public void done() {
finish();
}
}
And instead of having Context as a parameter you have TaskCallback
public class MyTask extends AsyncTask<Void, Void, Void> {
private TaskCallback mCallback;
public MyTask(TaskCallback callback) {
mCallback = callback;
}
//doinbackground, etc
protected void onPostExecute() {
mCallback.done();
}
There you go, it gives you more flexibility to custom each implementation.
I got the same situation, then I do as follows:
public class MyTask extends AsyncTask<Void, Void, Void> {
private Activity mActivity;
private Context mContext;
public MyTask(Activity activity) {
mActivity = activity;
mContext = mActivity.getApplicationContext();
}
//doinbackground, etc
protected void onPostExecute() {
mActivity.finish();
}
Hope it help :)
Define a method in your activity class like this:
public void FinishAfterAsyncTask()
{
this.finish();
}
And call this method from the OnPostExecute method of the AsynTask class.
You could create a new private AsyncTask extended from your public one.
In this private AsyncTask you have access to the Activity stuff and you can override the onPostExecute method to finish it.
Your truly AsyncTask
public class MyPublicAsyncTask extends AsyncTask<Void, Void, Void> {
Context context;
public GetHorariosAsyncTask(Context ctx){
context = ctx;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// prepare yourself for an async work
}
#Override
protected Void doInBackground(Void... params) {
// Do yout cool async stuff
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// you're finish, let's tell to user
}
}
Your Activity with private AsyncTask
public class MyActivity extends Activity {
Activity mAct;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mAct = this;
}
private class MyPrivateAsyncTask extends MyPublicAsyncTask {
public MyPrivateAsyncTask(Context ctx) {
super(ctx);
// TODO Auto-generated constructor stub
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
// our async task is completed! let's take care of this activity
mAct.finish();
}
}
}
Can you try
this.finish()
Seems like its because of calling it using mContext that it says undefined.
The project I'm working on is slightly more complicated but I made this simple test to try to track down what was wrong with my code. The progress dialog never dismisses. I had it at one point where they weren't returning null. '
public class SyncTestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new mTask(this).execute();
}
public class mTask extends AsyncTask<Void, Void, Void> {
Context mContext;
ProgressDialog progressDialog;
public mTask(Context aContext) {
mContext = aContext;
}
#Override
public void onPreExecute() {
progressDialog = new ProgressDialog(mContext);
progressDialog.setMessage("New...");
progressDialog.show();
}
#Override
public Void doInBackground(Void... params) {
return null;
}
public Void onPostExecute(Void... params) {
progressDialog.dismiss();
return null;
}
}
}
The parameters are wrong, use this:
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
return;
}
I am agree with Cesar and Shailendra answers, but still let me make little improvement over it:
#Override
protected void onPostExecute(Void result) {
if(progressDialog.isShowing())
{
progressDialog.dismiss();
}
return;
}
Missing #Override notation before onPostExecute. Also return null is not required.