Hi I am using ViewPager for auto swiping of 10 Text Quotes.When I open a app it starts from IMAGE1.Then it is keep on swiping upto the 10th quote.Let us consider,the viewpager showing 5th quote. Now I close it. When I open the app again it is starts from the first quote. But I need to show 6th Quote.
How do I resume the quote from where I have left before.
Quote 1:
Quote 5:
Quote 6:
UPDATE
int count=0;
int pager_position;
private void setTime_ToSlide() {
TextSlideShowAdapter adapter = new TextSlideShowAdapter(MainActivity.this, title1, title2);
myPager = (ViewPager) findViewById(R.id.reviewpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
Log.e("TEST", "Title Value Main " + title1 + " Title 2" + title2);
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (count1 <= 56) {
myPager.setCurrentItem(count1);
pager_position = myPager.getCurrentItem();
Log.e("Get current item", String.valueOf(myPager.getCurrentItem()));
count1++;
} else {
count1 = 0;
myPager.setCurrentItem(count1);
}
}
});
}
}, 500, 3000);
}
#Override
protected void onPause() {
super.onPause();
saveCurrentPagePosition();
Log.e("Get SharedPreference ", String.valueOf(pager_position));
}
#Override
protected void onResume() {
super.onResume();
//...
setCurrentPagePosition();
}
private void setCurrentPagePosition() {
myPager.setCurrentItem(pager_position);
}
private void saveCurrentPagePosition() {
// store current page position in shared preference
SharedPreferences.Editor editor = pref.edit();
editor.putInt("PagerPosition", pager_position);
editor.commit();
}
store your page position in sharedpreferences in onPause method and when you come back to app get page value from preferences and use that value to set current item
viewPager.setCurrentItem(postion from preferences);
As Ajinkya said store the current position of your pager in shared preference in onPause() of your Activity/Fragment.
#Override
public void onPause() {
super.onPause();
saveCurrentPagePosition();
}
Fetch the stored position in your Activity/Fragment onResume() and set the current position for ViewPager like
#Override
protected void onResume() {
super.onResume();
//...
setCurrentPagePosition();
}
Helper methods -
private void setCurrentPagePosition() {
// fetch from shared prefs or set default as 0
viewPager.setCurrentItem(postion_from_preferences);
}
private void saveCurrentPagePosition() {
// store current page position in shared preference
}
Related
When I press the back button, it returns to the main fragment. I am viewing pdf with webview. There are gifs in PDF. Clicking on these gifs opens in gif. When I press the back key, it goes to the application's home page, but I want it to stay in that fragment. I just want him out. When I press Backspace, I want to run the onBackPressed() function below.
public class AntrenmanProgramFragment extends Fragment {
public void onBackPressed() {
SharedPreferences sharedPref = getActivity().getSharedPreferences("sharedPref",Context.MODE_PRIVATE);
final String loginAntreman = sharedPref.getString("backAntreman", "kayıt yok");
tab = getActivity().findViewById(R.id.tabLayout);
new Handler().postDelayed(
new Runnable(){
#Override
public void run() {
if (loginAntreman.equals("0")){
tab.getTabAt(0).select();
}
if (loginAntreman.equals("1")){
tab.getTabAt(1).select();
}
}
}, 100);
}
}
Try adding #Override to override that method in android with your method when in the ui of xml you are now.
//just like so
#Override
public void onBackPressed()
{
SharedPreferences sharedPref = getActivity().getSharedPreferences("sharedPref",Context.MODE_PRIVATE);
final String loginAntreman = sharedPref.getString("backAntreman", "kayıt yok");
tab = getActivity().findViewById(R.id.tabLayout);
new Handler().postDelayed(
new Runnable(){
#Override
public void run() {
if (loginAntreman.equals("0")){
tab.getTabAt(0).select();
}
if (loginAntreman.equals("1")){
tab.getTabAt(1).select();
}
}
}, 100);
}
You are doing it in fragment witch don't have such method. Remove this part from here and add it to your activity.
public class YourActivity extends AppCompatActivity {
#Override
public void onBackPressed() {
SharedPreferences sharedPref = getActivity().getSharedPreferences("sharedPref",Context.MODE_PRIVATE);
final String loginAntreman = sharedPref.getString("backAntreman", "kayıt yok");
tab = findViewById(R.id.tabLayout);
new Handler().postDelayed(
new Runnable(){
#Override
public void run() {
if (loginAntreman.equals("0")){
tab.getTabAt(0).select();
}
if (loginAntreman.equals("1")){
tab.getTabAt(1).select();
}
}
}, 100);
}
}
Or if for some reason you need to do it in fragment here is a link how to handle onBackPressed in fragments. How to implement onBackPressed() in Fragments?
I'm developing a feed app, where people can make posts and these posts will populate a RecyclerView.
I have a FAB button that leads to a post activity, but when I post and then comeback to the MainActivity the list is not updated. But when I use the logout button and log back in, the list gets updated, or when I launch the activity it works.
I think this happens because my Async function gets called to work on onCreate, but I can't work like these, I need the AsyncTask to automatically fetch, otherwise people won't get the list updated in real time.
Could you please show me a light in the dark? Here are the codes for MainActivity, PostActivity and logout function from another class.
Main Activity:
public class MainActivity extends AppCompatActivity {
private AppCompatActivity activity = MainActivity.this;
private RecyclerView recyclerViewNews;
private List<Noticia> listNoticias;
private NewsRecyclerAdapter newsRecyclerAdapter;
private DBNoticias databaseHelper;
private Button btnLogout;
private LinearLayoutManager mLayoutManager;
UserSession userSession;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userSession = new UserSession(getApplicationContext());
recyclerViewNews = findViewById(R.id.recyclerViewNews);
btnLogout = findViewById(R.id.btlogout);
TextView usuario = findViewById(R.id.textView5);
/**
* Olá mundo by Alciomar
*/
SharedPreferences sharedPreferences = getSharedPreferences("Reg", Context.MODE_PRIVATE);
String uName = sharedPreferences.getString("Name", "");
usuario.setText(uName.toUpperCase());
try {
btnLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
userSession.logoutUser();
}
});
} catch (Exception e) {
e.printStackTrace();
}
initStuff();
getDataFromPostgres();
FloatingActionButton fab = findViewById(R.id.fabNews);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, PostNews.class);
startActivity(intent);
}
});
}
/**
* This method is to initialize objects to be used
*/
private void initStuff() {
try {
listNoticias = new ArrayList<>();
newsRecyclerAdapter = new NewsRecyclerAdapter(listNoticias);
mLayoutManager = new LinearLayoutManager(getApplicationContext());
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
recyclerViewNews.setLayoutManager(mLayoutManager);
recyclerViewNews.setItemAnimator(new DefaultItemAnimator());
recyclerViewNews.setHasFixedSize(true);
recyclerViewNews.setAdapter(newsRecyclerAdapter);
databaseHelper = new DBNoticias(activity);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* This method is to fetch all user records from SQLite
*/
private void getDataFromPostgres() {
// AsyncTask is used that SQLite operation not blocks the UI Thread.
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
listNoticias.clear();
for (DBNoticias dbNoticias : databaseHelper.getNewsList()) {
Noticia noticia = new Noticia();
noticia.setUser_id(dbNoticias.getId());
noticia.setNewsTitle(dbNoticias.getNewsTitle());
noticia.setNewsMessage(dbNoticias.getNewsPost());
listNoticias.add(noticia);
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
newsRecyclerAdapter.notifyDataSetChanged();
}
}.execute();
}
Post News Activity:
public class PostNews extends AppCompatActivity {
private DBNoticias dbNoticias;
private Button btnpostar;
private EditText editTextCDNewsTitle;
private EditText editTextCDNewsPost;
private Noticia noticia;
private SharedPreferences sharedPreferences;
public void alert(String titulo, String txt){
AlertDialog alertDialog = new AlertDialog.Builder(PostNews.this).create();
alertDialog.setTitle(titulo);
alertDialog.setMessage(txt);
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_news);
btnpostar = findViewById(R.id.btn_postar);
dbNoticias = new DBNoticias();
editTextCDNewsTitle = findViewById(R.id.EditTextNewsTitle);
editTextCDNewsPost = findViewById(R.id.EditTextNewsPost);
}
public void salvarNoticia(View view) {
try {
{
String newsTitle = editTextCDNewsTitle.getText().toString();
String newsPost = editTextCDNewsPost.getText().toString();
if (!(editTextCDNewsTitle.getText().toString().equals("") || editTextCDNewsTitle.getText() == null ||
editTextCDNewsPost.getText().toString().equals("") || editTextCDNewsPost.getText() == null
)) {
sharedPreferences = getSharedPreferences("Reg", Context.MODE_PRIVATE);
String uName = sharedPreferences.getString("Name", "");
String uEmail = sharedPreferences.getString("Email", "");
int uIdUser = sharedPreferences.getInt("IdUser", 0);
dbNoticias.setNewsTitle(newsTitle);
dbNoticias.setNewsPost(newsPost);
dbNoticias.setIdUser(uIdUser);
dbNoticias.salvar();
noticia = new Noticia();
Toast.makeText(getApplicationContext(), "Notícia postada com sucesso",
Toast.LENGTH_LONG).show();
editTextCDNewsTitle.setText("");
editTextCDNewsPost.setText("");
}
}
}
catch (Exception e){
alert("Erro", e.getMessage());
}
}
Thank you in advance if you read and try to help!
There are multiple ways to do this:
Method 1 – Use onResume()
If you call your getDataFromPostgres() method in onResume instead of onCreate, it'll fetch data and refresh list every time the activity wakes from a pause (for example coming back from another activity)
// existing code
#Override
public void onResume(){
super.onResume();
getDataFromPostgres()
}
(This would be the simplest solution)
Method 2 – Poll the DB continuously
If there are other services that might be updating the database and you need to always show the latest state in the activity, another way (although really inefficient) would be to keep refreshing the list after a defined time period (let's say 10 seconds as an example).
How to run an async task for every x mins in android?
Method 3 – Use onActivityResult
If you want to update the list only when a new entry has been created in the second activity, you can use onActivityResult to notify the first activity on action and then refresh your list there.
How to manage `startActivityForResult` on Android?
Please use this, it's working for me
newsRecyclerAdapter.notifyItemInserted(position);
newsRecyclerAdapter.notifyDataSetChanged();
I have an android project that is using fragments and a viewpager.
I am using a separate countdown timer for every page, that only runs when the view of the page is 'onscreen'. At first the time for every page is the same, but after a while page 1 might be 20 seconds left, page 2 60 seconds and so on.
My problem is that I don't know how to save the remaining time, the moment the user swipes to the next page. I am using a onpagestatelistener that has the following code, but this is saving the new value of questionId and the old value of the new time. How do I refer to the value of the questionId and the matching newtime-value of the page that was in view before the user swiped?
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
saveTime();
}
}
public void onPageScrolled(int position, float arg1, int arg2) {}
public void onPageSelected(int pos) {
questionId = mQuestions.get(pos).getNr()
runTime();
}
});
public void saveTime(){
mQuestions.get(questionId).setTime(newTime);
}
public void runTime(){
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
mTimer = new CountDownTimer(90000, 1000) {//MillisInFuture, countDownInterval
public void onTick(long millisUntilFinished) {
newTime = (millisUntilFinished/1000);
}
public void onFinish() {
}
}.start();
}
First of all you can use SharedPreferences.
Besides, of course you can save data in adapter which you use for ViewPager, you can save this data in DB or create some singleInstance in your parent Activity or Fragment.
I'm trying to use an AsyncTaskLoader to load data in the background to populate a detail view in response to a list item being chosen. I've gotten it mostly working but I'm still having one issue. If I choose a second item in the list and then rotate the device before the load for the first selected item has completed, then the onLoadFinished() call is reporting to the activity being stopped rather than the new activity. This works fine when choosing just a single item and then rotating.
Here is the code I'm using. Activity:
public final class DemoActivity extends Activity
implements NumberListFragment.RowTappedListener,
LoaderManager.LoaderCallbacks<String> {
private static final AtomicInteger activityCounter = new AtomicInteger(0);
private int myActivityId;
private ResultFragment resultFragment;
private Integer selectedNumber;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myActivityId = activityCounter.incrementAndGet();
Log.d("DemoActivity", "onCreate for " + myActivityId);
setContentView(R.layout.demo);
resultFragment = (ResultFragment) getFragmentManager().findFragmentById(R.id.result_fragment);
getLoaderManager().initLoader(0, null, this);
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d("DemoActivity", "onDestroy for " + myActivityId);
}
#Override
public void onRowTapped(Integer number) {
selectedNumber = number;
resultFragment.setResultText("Fetching details for item " + number + "...");
getLoaderManager().restartLoader(0, null, this);
}
#Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return new ResultLoader(this, selectedNumber);
}
#Override
public void onLoadFinished(Loader<String> loader, String data) {
Log.d("DemoActivity", "onLoadFinished reporting to activity " + myActivityId);
resultFragment.setResultText(data);
}
#Override
public void onLoaderReset(Loader<String> loader) {
}
static final class ResultLoader extends AsyncTaskLoader<String> {
private static final Random random = new Random();
private final Integer number;
private String result;
ResultLoader(Context context, Integer number) {
super(context);
this.number = number;
}
#Override
public String loadInBackground() {
// Simulate expensive Web call
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Item " + number + " - Price: $" + random.nextInt(500) + ".00, Number in stock: " + random.nextInt(10000);
}
#Override
public void deliverResult(String data) {
if (isReset()) {
// An async query came in while the loader is stopped
return;
}
result = data;
if (isStarted()) {
super.deliverResult(data);
}
}
#Override
protected void onStartLoading() {
if (result != null) {
deliverResult(result);
}
// Only do a load if we have a source to load from
if (number != null) {
forceLoad();
}
}
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
result = null;
}
}
}
List fragment:
public final class NumberListFragment extends ListFragment {
interface RowTappedListener {
void onRowTapped(Integer number);
}
private RowTappedListener rowTappedListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
rowTappedListener = (RowTappedListener) activity;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(getActivity(),
R.layout.simple_list_item_1,
Arrays.asList(1, 2, 3, 4, 5, 6));
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
ArrayAdapter<Integer> adapter = (ArrayAdapter<Integer>) getListAdapter();
rowTappedListener.onRowTapped(adapter.getItem(position));
}
}
Result fragment:
public final class ResultFragment extends Fragment {
private TextView resultLabel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.result_fragment, container, false);
resultLabel = (TextView) root.findViewById(R.id.result_label);
if (savedInstanceState != null) {
resultLabel.setText(savedInstanceState.getString("labelText", ""));
}
return root;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("labelText", resultLabel.getText().toString());
}
void setResultText(String resultText) {
resultLabel.setText(resultText);
}
}
I've been able to get this working using plain AsyncTasks but I'm trying to learn more about Loaders since they handle the configuration changes automatically.
EDIT: I think I may have tracked down the issue by looking at the source for LoaderManager. When initLoader is called after the configuration change, the LoaderInfo object has its mCallbacks field updated with the new activity as the implementation of LoaderCallbacks, as I would expect.
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
LoaderInfo info = mLoaders.get(id);
if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
if (info == null) {
// Loader doesn't already exist; create.
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
if (DEBUG) Log.v(TAG, " Created new loader " + info);
} else {
if (DEBUG) Log.v(TAG, " Re-using existing loader " + info);
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}
if (info.mHaveData && mStarted) {
// If the loader has already generated its data, report it now.
info.callOnLoadFinished(info.mLoader, info.mData);
}
return (Loader<D>)info.mLoader;
}
However, when there is a pending loader, the main LoaderInfo object also has an mPendingLoader field with a reference to a LoaderCallbacks as well, and this object is never updated with the new activity in the mCallbacks field. I would expect to see the code look like this instead:
// This line was already there
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
// This line is not currently there
info.mPendingLoader.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
It appears to be because of this that the pending loader calls onLoadFinished on the old activity instance. If I breakpoint in this method and make the call that I feel is missing using the debugger, everything works as I expect.
The new question is: Have I found a bug, or is this the expected behavior?
In most cases you should just ignore such reports if Activity is already destroyed.
public void onLoadFinished(Loader<String> loader, String data) {
Log.d("DemoActivity", "onLoadFinished reporting to activity " + myActivityId);
if (isDestroyed()) {
Log.i("DemoActivity", "Activity already destroyed, report ignored: " + data);
return;
}
resultFragment.setResultText(data);
}
Also you should insert checking isDestroyed() in any inner classes. Runnable - is the most used case.
For example:
// UI thread
final Handler handler = new Handler();
Executor someExecutorService = ... ;
someExecutorService.execute(new Runnable() {
public void run() {
// some heavy operations
...
// notification to UI thread
handler.post(new Runnable() {
// this runnable can link to 'dead' activity or any outer instance
if (isDestroyed()) {
return;
}
// we are alive
onSomeHeavyOperationFinished();
});
}
});
But in such cases the best way is to avoid passing strong reference on Activity to another thread (AsynkTask, Loader, Executor, etc).
The most reliable solution is here:
// BackgroundExecutor.java
public class BackgroundExecutor {
private static final Executor instance = Executors.newSingleThreadExecutor();
public static void execute(Runnable command) {
instance.execute(command);
}
}
// MyActivity.java
public class MyActivity extends Activity {
// Some callback method from any button you want
public void onSomeButtonClicked() {
// Show toast or progress bar if needed
// Start your heavy operation
BackgroundExecutor.execute(new SomeHeavyOperation(this));
}
public void onSomeHeavyOperationFinished() {
if (isDestroyed()) {
return;
}
// Hide progress bar, update UI
}
}
// SomeHeavyOperation.java
public class SomeHeavyOperation implements Runnable {
private final WeakReference<MyActivity> ref;
public SomeHeavyOperation(MyActivity owner) {
// Unlike inner class we do not store strong reference to Activity here
this.ref = new WeakReference<MyActivity>(owner);
}
public void run() {
// Perform your heavy operation
// ...
// Done!
// It's time to notify Activity
final MyActivity owner = ref.get();
// Already died reference
if (owner == null) return;
// Perform notification in UI thread
owner.runOnUiThread(new Runnable() {
public void run() {
owner.onSomeHeavyOperationFinished();
}
});
}
}
Maybe not best solution but ...
This code restart loader every time, which is bad but only work around that works - if you want to used loader.
Loader l = getLoaderManager().getLoader(MY_LOADER);
if (l != null) {
getLoaderManager().restartLoader(MY_LOADER, null, this);
} else {
getLoaderManager().initLoader(MY_LOADER, null, this);
}
BTW. I am using Cursorloader ...
A possible solution is to start the AsyncTask in a custom singleton object and access the onFinished() result from the singleton within your Activity. Every time you rotate your screen, go onPause() or onResume(), the latest result will be used/accessed. If you still don't have a result in your singleton object, you know it is still busy or that you can relaunch the task.
Another approach is to work with a service bus like Otto, or to work with a Service.
Ok I'm trying to understand this excuse me if I misunderstood anything, but you are losing references to something when the device rotates.
Taking a stab...
would adding
android:configChanges="orientation|keyboardHidden|screenSize"
in your manifest for that activity fix your error? or prevent onLoadFinished() from saying the activity stopped?
I have spent many hours looking for a solution to this and need help.
I have a nested AsyncTask in my Android app Activity and I would like to allow the user to rotate his phone during it's processing without starting a new AsyncTask. I tried to use onRetainNonConfigurationInstance() and getLastNonConfigurationInstance().
I am able to retain the task; however after rotation it does not save the result from onPostExecute() to the outer class variable. Of course, I tried getters and setters. When I dump the variable in onPostExecute, that it is OK. But when I try to access to the variable from onClick listener then it is null.
Maybe the code will make the problem clear for you.
public class MainActivity extends BaseActivity {
private String possibleResults = null;
private Object task = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.task = getLastNonConfigurationInstance();
setContentView(R.layout.menu);
if ((savedInstanceState != null)
&& (savedInstanceState.containsKey("possibleResults"))) {
this.possibleResults = savedInstanceState
.getString("possibleResults");
}
if (this.possibleResults == null) {
if (this.task != null) {
if (this.task instanceof PossibleResultWebService) {
((PossibleResultWebService) this.task).attach();
}
} else {
this.task = new PossibleResultWebService();
((PossibleResultWebService) this.task).execute(this.matchToken);
}
}
Button button;
button = (Button) findViewById(R.id.menu_resultButton);
button.setOnClickListener(resultListener);
}
#Override
protected void onResume() {
super.onResume();
}
OnClickListener resultListener = new OnClickListener() {
#Override
public void onClick(View v) {
Spinner s = (Spinner) findViewById(R.id.menu_heatSpinner);
int heatNo = s.getSelectedItemPosition() + 1;
Intent myIntent = new Intent(MainActivity.this,
ResultActivity.class);
myIntent.putExtra("matchToken", MainActivity.this.matchToken);
myIntent.putExtra("heatNo", String.valueOf(heatNo));
myIntent.putExtra("possibleResults",
MainActivity.this.possibleResults);
MainActivity.this.startActivityForResult(myIntent, ADD_RESULT);
}
};
private class PossibleResultWebService extends AsyncTask<String, Integer, Integer> {
private ProgressDialog pd;
private InputStream is;
private boolean finished = false;
private String possibleResults = null;
public boolean isFinished() {
return finished;
}
public String getPossibleResults() {
return possibleResults;
}
#Override
protected Integer doInBackground(String... params) {
// quite long code
}
public void attach() {
if (this.finished == false) {
pd = ProgressDialog.show(MainActivity.this, "Please wait...",
"Loading data...", true, false);
}
}
public void detach() {
pd.dismiss();
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(MainActivity.this, "Please wait...",
"Loading data...", true, false);
}
#Override
protected void onPostExecute(Integer result) {
possibleResults = convertStreamToString(is);
MainActivity.this.possibleResults = possibleResults;
pd.dismiss();
this.finished = true;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (this.possibleResults != null) {
outState.putString("possibleResults", this.possibleResults);
}
}
#Override
public Object onRetainNonConfigurationInstance() {
if (this.task instanceof PossibleResultWebService) {
((PossibleResultWebService) this.task).detach();
}
return (this.task);
}
}
It is because you are creating the OnClickListener each time you instantiate the Activity (so each time you are getting a fresh, new, OuterClass.this reference), however you are saving the AsyncTask between Activity instantiations and keeping a reference to the first instantiated Activity in it by referencing OuterClass.this.
For an example of how to do this right, please see https://github.com/commonsguy/cw-android/tree/master/Rotation/RotationAsync/
You will see he has an attach() and detach() method in his RotationAwareTask to solve this problem.
To confirm that the OuterClass.this reference inside the AsyncTask will always point to the first instantiated Activity if you keep it between screen orientation changes (using onRetainNonConfigurationInstance) then you can use a static counter that gets incremented each time by the default constructor and keep an instance level variable that gets set to the count on each creation, then print that.