First of all, some info about my project:
I have an application that consists of several fragments. (I have one class that extends FragmentActivity and another one that extends FragmentPagerAdapter.)
So actually my code is running inside the Fragments.
I call an asynctask inside one of the fragments to do some calculations. The asyncTask is a seperate file and the class is not located inside the Fragment class.
So 1 file is the asynctask and another one the fragmet (variables from the fragment are not accessible direct by the asynctask!!!).
I can display the result of the asyncTask by using ProgressDialog.
However I want to be able to return the data (result of the asynctask) back to a variable that I have in my fragment. What I have tried so far is:
Using get() from asyncatask.execute()
I tried to do it like this:
I used the following code that was called after a button click.
mytask1 = new myAsyncTask(this);
String result =mytask1.execute(value1).get();
However this results in the main thread to get stuck and wait for the asynctask to complete.
2.Using loginSharePreferens
loginPreferences = getActivity().getSharedPreferences("loginPrefs", Context.MODE_PRIVATE);
loginPrefsEditor = loginPreferences.edit();
loginPrefsEditor.putString("result", result);
loginPrefsEditor.commit();
This gave me errors.
3.I tried also this
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext() );
That was similar with the 2nd method.
4.I tried to create a method in my fragment that would just set the value and I tried to call it inside the fragment
MyFrragment1.this.setRestult(1); // is called in the onPostExecute of the asyncTask
public void setRestult(int result){
this.test1=result; ///inside of the fragment
}
This gave me error: "No enclosing instance of the type MyFragment1 is accessible in scope"
I don't know what else to try. Any ideas ?
You can use the onPostExecute method which runs in the UI thread and is called after doInBackground finishes. You can override it in your Fragment like this:
new myAsyncTask() {
#Override
protected void onPostExecute( Result result ) {
super.onPostExecute( result );
// Do something with result here
}
}.execute(value1);
Related
I have one method(let's call it getData) in my fragment(let's call it List) which I call in onCreateView.
This method load some data from server and put it to some views.
In my fragment I have one button which open another fragment(Let's call it Detail), and when I go back to List onCreateView calling again and data start load again.
I tried to put getData into onCreate... and in fact it must works, and mustn't call getData again...
But getData works with views whick initialize only in onCreateView and another methods after onCreateView and all that methods always recalling when I return to List from Detail.
How do I make don't recall getData when I return to List from Detail.
I'm so sorry for my bad English and grammar mistakes.
Thanks.
first of All override onStop method by Ctrl+O
it will look like this
public class yourFragment extends Fragment{
boolean isReturned = false;
#Override
public void onStop() {
super.onStop();
isReturned = true;
}
public void getData(){
if(!isReturned){
//fetch data
}
}
i have a setting Activity that store name , by changing the name it must first send that to my server and if its store in server successfully then it should set in the summary of my EditTextPreference .
everything works fine but at the end i cant touch the EditTextPreference to set name on it.
this method is in setting activity but called from onPostExecute of the AsyncTask
public void setNewSetting(Activity activity) {
EditTextPreference editTextPreference = (EditTextPreference) UserSettingActivity.this.findPreference(activity.getString(R.string.pref_name_key));
name = sharedPreferences.getString(activity.getString(R.string.pref_name_key), "");
editTextPreference.setSummary(name);
}
the activity is the setting activity that i passed to the AsyncTask and then passed to method.
my problem is here and give me a nullPoiterException for EditTextPreferences
Sorry for my bad english.
and thanks in advance.
Method 1:
If activity is still in background, pass your context to AsyncTask and create an instance of your Settings Activity.
SettingsActivity settingsActivity = (SettingsActivity) context;
then, call the method in onPostExecute()
settingsActivity.setNewSetting();
And, have your setNewSetting() method in your SettingsActivity. It should be public and put some checks for null values.
Method 2:
Use an interface delegate. Create an interface:
public interface TaskListener {
void onComplete();
}
Pass it to AsyncTask when you execute it, something like:
new MyAsyncTask(params, params, new TaskListener() {
#Override
public void onComplete () {
// call setNewSetting from within SettingsActivity
}
}).execute();
You get it in your AsyncTask constructer:
public MyAsyncTask (String params, String param2, TaskListener taskListenerDelegate) {
this.taskListenerDelegate = taskListenerDelegate;
}
Call its onComplete() in onPostExecute() :
taskListenerDelegate.onComplete();
Method 3
Not recommended, but you can try with startActivityForResult() too. And, listen in onActivityResult() to apply changes.
I've an Activity A that contains a Login Fragment and an Activity B that contains a Home Fragment.
I've to start B from Login Fragment after a succesfully login request (async).
I've a callback listener inside the login fragment:
onSuccess(result) {
startActivity(B);
}
Today I met this nice bug: getting exception "IllegalStateException: Can not perform this action after onSaveInstanceState".
I think that's not properly a bug, anyway I don't know how to workaround that. This blog post suggests to avoid transaction inside async callback methods, yeah but how? commitAllowingStateLoss() should be used as a last resort: in case, should I use it inside Home Fragment transaction in Activity B creation method?
Basically, what should I do to start another activity after async callback?
You should use onPostExecute(result) in the AsyncTask:
private class LoginTask extends AsyncTask<parameters,...> {
...
protected void onPostExecute(Long result) {
//if result successful start ActivityB
}
}
Onpost fires after the asynctask is complete.
It runs on the UI thread so that should solve your problem.
Put this in your main activity:
public void run(){
//code you would normally have after task completes
}
Then put this in your onSuccess:
mainactivity.runUIonthread()
Scenario: I have a dialog fragment. Onclick of an image it launches an activity which does the process in an asynctask. When I get back the result the activity finishes and goes back to the dialog fragment.On getting back the image must be changed.
Problem:The image remains the same and only when you close the dialogfragment and reopen it does it change.
Sorry I havnt posted the code, Just wanted some suggestions on how to update the view from the activitys async task.
If I understood you correctly, try use invalidate() method for your ImageView in onPostExecute() of your AsyncTask.
If you start your AsyncTask in launched Activity, as I suppose, you can start custom Activity in Dialog Fragment and pass your ImageView pointer to constructor. Something like this.
public class AsyncTaskActivity extends Activity{
private ImageView yourImage;
public AsyncTaskActivity(ImageView yourImage){
this.yourImage = yourImage;
}
....
//your AsyncTask should be like this
new AsyncTask<Void, Void, Void>(){
//here your backround process
...
//here we invalidate ImageView
#Override
protected void onPostExecute(Void result) {
//update image Bitmap or something else
...
yourImage.invalidate();
}
}.execute();
}
With best regards.
I would suggest the following:
Start the activity (B) by using startActivityForResult from your dialog.
Override OnActivityResult in your original activity (A, the one that host the dialog).
call super.OnAcitivityResult in it, so that the dialog can receive the call back.
Your dialogfragment should override OnActivityResult and change the image based on the result.
Need your code to see what you are actually trying to do.
I'm trying to understand under what circumstances can getActivity() return null in a fragment AFTER onAttach. I typically start an async task in onCreate or onCreateView inside my fragments but I'm getting error reports indicating sometimes getActivity() is null when the async task finishes. Error reports are coming in via crashlytics but can't reproduce them.
The async tasks are "blocking" - I display a modal non-dismissable progress bar. Also rotation is prevented by calling setRequestedOrientation.
I'm using v4 support Fragment and FragmentActivity. Fragments are set to retain state.
What am I missing? Are there other config changes that may cause the fragment to be detached?
I tried temporarily enabling rotation and the dev option to destroy activity after leaving it but still can't reproduce this...
Here's some of the relevant code inside one of my fragments, in this case it would sometimes break with an NPE at activity.dismissSpinner:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkIfLoggedIn();
}
public void checkIfLoggedIn() {
LoginActivity activity = (LoginActivity)getActivity();
activity.showSpinner("Connecting, please wait...");
AsyncTask<String, Void, JsonResponse> asyncTask = new AsyncTask<String, Void, JsonResponse>() {
protected JsonResponse doInBackground(String... notused) {
return cmsServer().getCurrentUser(getActivity());
}
protected void onPostExecute(JsonResponse result) {
LoginActivity activity = (LoginActivity)getActivity();
activity.dismissSpinner();
//...more stuff here
}
};
asyncTask.execute();
}
Do you stop/cancel your AsyncTask if your app goes to background or is paused?
Consider the following scenario: your AsyncTask is executed, and when prompted with the progress bar, the user decides to do other stuff while she waits for the task to complete. She does so by pressing the home button. Alas, this might destroy the fragment and the activity. The running AsyncTask knows nothing about it, and when done, getActivity() method invocations (or local variables pointing to a non-existent Activity) may as well return null, causing your app to crash.
The Fragmentlife cycle is as follows
According to Fragment life-cycle onCreate() and onCreateView()are called before the Activity creation. so when we call getActivity() in these methods in returns null.
so instead of starting the async task in the onCreateView() start it in onStart() or onResume() so that getActivity() returns the exact Activity reference.
For more details click here