How to avoid recreating viewing onCreate on Android?

I have a FragmentActivity that shows a list of contacts.

Here is my onCreate method:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_human_list); if (findViewById(R.id.human_detail_container) != null) { // The detail container view will be present only in the // large-screen layouts (res/values-large and // res/values-sw600dp). If this view is present, then the // activity should be in two-pane mode. mTwoPane = true; // In two-pane mode, list items should be given the // 'activated' state when touched. ((HumanListFragment) getSupportFragmentManager() .findFragmentById(R.id.human_list)) .setActivateOnItemClick(true); } if (savedInstanceState == null || !savedInstanceState.getBoolean("displayed_contacts")) displayContacts(); } 

My onSaveInstanceState :

 @Override protected void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); savedInstanceState.putBoolean("displayed_contacts", true); } 

And I'm not sure if this is relevant, but here is my displayContacts just in case:

 private void displayContacts() { // Init variables String[] SelectColumns = new String[] { Contacts._ID, Contacts.DISPLAY_NAME_PRIMARY, Contacts.PHOTO_URI }; String rawContactID, displayName, phoneNumber; InputStream thumbnailPhoto; Cursor c, infoC; // Outer cursor (fetches all contact IDs) c = getContentResolver().query( Contacts.CONTENT_URI, SelectColumns, Contacts.HAS_PHONE_NUMBER + " = 1 ", null, Contacts.DISPLAY_NAME_PRIMARY); Log.v(getPackageName(), "Found " + (c != null ? c.getCount() : "0") + " contacts"); try { if (c.moveToFirst()) { do { // Columns rawContactID = c.getString(c.getColumnIndex(SelectColumns[0])); displayName = c.getString(c.getColumnIndex(SelectColumns[1])); String[] selectPhone = {CommonDataKinds.Phone.NUMBER}; thumbnailPhoto = openThumbnail(Long.valueOf(rawContactID)); infoC = getContentResolver().query( CommonDataKinds.Phone.CONTENT_URI, selectPhone, CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] {rawContactID}, null ); infoC.moveToFirst(); phoneNumber = infoC.getString(0); // Adds items to ListView HumanContent.addItem(new HumanContent.HumanItem(rawContactID, displayName, phoneNumber != "n/a" ? phoneNumber : "", thumbnailPhoto)); Log.v(getPackageName(), "Cursor position: " + c.getPosition() + ", contact ID: " + rawContactID); infoC.close(); } while (c.moveToNext()); c.close(); } displayed_contacts = true; } catch (Exception e) { Log.e(getPackageName(), e.getMessage()); } } 

Now here is what:

When I use the back key to exit the application, and then open it again with the icon; the list is recreated even if it is stored in memory: therefore, I get a double list of contacts in the same view.

savedInstanceState in this case is zero, so the if condition is met, but in fact the view already has my previous contact list. What gives? How can I avoid recreating the list? I already tried using instance variables instead, but to no avail.

I would also like to avoid re-creating the list 100% of the time - if I can reuse an existing view, amazing.

+7
android
source share
11 answers

First, the reason your savedInstanceState is null. The system saves only the state of actions that are destroyed due to system restrictions. If you return from Activity, it will be destroyed forever, and no state will be saved.

Relevant documents: http://developer.android.com/training/basics/activity-lifecycle/recreating.html

When your activity is destroyed because the user clicks Back or the activity itself ends, the system concept of this activity is gone forever, because behavior indicates activity is no longer required. However, if the system destroys to system limitations (and not to normal application behaviors), then although the actual instance of the Activity has disappeared, the system remembers that it existed such that if the user goes to it, the system creates a new instance of the action using the set of saved data, which describes the state of activity when it was destroyed.

So, it seems that your specific problem is that until your activity has passed, your static HumanContact class is still in memory, and your new activity loads it with another copy of your contacts.

There are several ways to solve this problem. First, you can implement the HumanContent method to clear all its elements and call it whenever you start a new instance of your activity. This will be useful to keep your data up to date, but that means you need to reload your contacts.

Secondly, if you really want to avoid data reloading, I would recommend creating some kind of cache for contacts that are not dependent on Activity. You should consider your activity as quite transient, it can and will be destroyed and recreated often, while the cache can be saved.

HumanContent seems to already completely fill this responsibility. You use it to store your data, and it is stored outside the life cycle of your activity. You can optionally add a method to it that checks whether contacts are loaded, and if they do not download them themselves. Thus, it has full control over the loading and caching of your data, and actions may be solely responsible for displaying this data. Be careful with this type of solution that you do not store too much data in memory, that you reload the cache at any time when you expect your data to be changed, and keep in mind that in some cases your process may be restarted by the system, therefore, your cache should be ready to reload your data if it is destroyed.

As for the preservation of your ideas, if the user abandons his activity, then the final () is called, and your activity will be destroyed. Remember that in this case, the system no longer has a concept of activity, so there will be no way to save these views for reuse.

+8
source share

Simple follow these steps in your activity

  • Declare your list object and listview_adapter object in your Activity class.
  • Initialize your list object and listview_adapter object in the OnCreate () method and add the contents to yourContacts () screen.

Then definitely you will not get content replication.

+3
source share

It is always recommended to use caching to save data. since the mention of Groucho u may come with storage options For more details see the link below.

http://developer.android.com/guide/topics/data/data-storage.html

+1
source share

I ran into a similar problem once. I'm not sure how legal this is, but the code I used is below, and it fixed a lot:

 private static ViewGroup view1; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mCurrentActivity = getActivity(); if (view1 == null) { settleFragment(inflater); } else { if (view1.getParent() != null && view1.getParent() instanceof ViewGroup) { ((ViewGroup) view1.getParent()).removeView(view1); } } return view1; } 

You can adapt the settleFragment(inflater); method settleFragment(inflater); with your. Magic is a static variable called view1 . After the fragment is initialized, it is filled with data. Other instances of fragments will simply break view1 with its ex-parent and insert it themselves.

This is pretty fast regarding the file storage cache, since the object is stored in ram. If OS garbage collects the object, the static variable will again be empty, and duplicates will not be repeated when the view is recreated.

+1
source share

Unable to stop the onCreate function. However, you can apply a crawl to avoid duplicating the list, you can remove all items from the list, and then let it re-populate the list.

+1
source share
 @Override public void onPause () { super.onPause(); //........... } @Override public void onStop () { super.onPause(); //............ } 

Check if you can use these methods in your snippets?

+1
source share

The easiest way to achieve this is to make Nullcheck
those.

 if(yourcomponent==null) { initializecomponent(); } 


This may interfere with the recreation of your views.

+1
source share

when you are done loading data into displayContacts (), you can save the flag (display_contacts) in the general settings. In onCreate (), check the preference value and call your displayContacts () accordingly.

0
source share

I faced the same problem when using fragments.

We have existing methods as described above. If you find yourself in a difficult position to use, then you can try as follows: -

  • Initiate a boolean with false.
  • Set the Boolean to true after receiving your data.
  • Now, when you re-initiate your OnCreate () check, this boolean value will be true or false. if false, you need to extract this data again, otherwise you will not need to receive this data. Put a condition for the same.
0
source share

You are about to check the controller for this.

Instead, try checking the value you saved. First take one variable as a bundle. Save it in the onCreate method.

 Bundle bdlSaveInstant; // Declare at top before onCreate() method. /* Initialise in onCreate() method. After super.onCreate(savedInstanceState); setContentView(R.layout.activity_human_list); bdlSaveInstant = savedInstanceState; */ @override onBackPressed() { bdlSaveInstant.putBoolean("displayed_contacts", true); } @override onDestroy() { bdlSaveInstant.putBoolean("displayed_contacts", true); } 

Try it, it will work.

0
source share

In your create method, just clear your list. Because every time he goes to the create method and clears the list (which), this is your previous data load.

OR

check your if list (list.size == null), then call your API otherwise in the else block (list.setAdapter).

hope this works.

0
source share

All Articles