这是我的onCreate方法:
@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(); }
我的onSaveInstanceState:
@Override protected void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); savedInstanceState.putBoolean("displayed_contacts",true); }
而且我不确定这是否相关,但这是我的displayContacts以防万一:
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,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()); } }
现在是这样的:
当我使用后退键退出应用程序,然后通过图标再次打开它时;即使列表保存在内存中,列表也会重新创建:所以我在同一视图中获得了一个双重联系人列表.
在这种情况下,savedInstanceState为null,因此达到了if条件,但实际上该视图已经有了我之前的联系人列表.是什么赋予了?如何避免重新创建列表?我已经尝试过使用实例变量,但无济于事.
我还想避免100%重复列表 – 如果我可以重用现有的视图,真棒.
解决方法
相关文档:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
When your activity is destroyed because the user presses Back or the
activity finishes itself,the system’s concept of that Activity
instance is gone forever because the behavior indicates the activity
is no longer needed. However,if the system destroys the activity due
to system constraints (rather than normal app behavior),then although
the actual Activity instance is gone,the system remembers that it
existed such that if the user navigates back to it,the system creates
a new instance of the activity using a set of saved data that
describes the state of the activity when it was destroyed.
因此,看起来您的特定问题是,当您的Activity消失时,您的静态HumanContact类仍然在内存中,而您的新Activity将使用另一个联系人副本加载它.
有几种方法可以解决这个问题.首先,您可以在HumanContent上实现一个方法来清除其所有项目,并在您启动Activity的新实例时调用它.这样可以确保您的数据是最新的,但这意味着您必须重新加载您的联系人.
其次,如果你想真正避免重新加载数据,我建议为独立于Activity的联系人创建某种缓存.您应该将Activity视为相当短暂的,它可以并且将被频繁地销毁和重新创建,而缓存可以持久存在.
HumanContent似乎已经在某种程度上填补了这一责任.您正在使用它来存储您的数据,并且它会持续超出您的Activity的生命周期.您还可以向其添加一个方法,以检查是否已加载联系人,如果没有加载它们本身.这样,它就可以完全控制加载和缓存数据,而活动只能负责显示这些数据.请注意这种类型的解决方案,即您没有在内存中存储太多数据,而是在您希望数据发生更改时重新加载缓存,并注意在某些情况下系统可能会重新启动您的进程,因此您的缓存必须准备好重新加载您的数据,以防它被销毁.
至于保留您的视图,如果用户退出您的Activity,则调用finish(),并且您的Activity将被销毁.请记住,在这种情况下,系统不再具有Activity的任何概念,因此无法保留这些视图以供重用.