Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何避免在Android上的onCreate上重新创建视图?_Android - Fatal编程技术网

如何避免在Android上的onCreate上重新创建视图?

如何避免在Android上的onCreate上重新创建视图?,android,Android,我有一个显示联系人列表的FragmentActivity 以下是我的onCreate方法: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_human_list); if (findViewById(R.id.human_detail_container)

我有一个显示联系人列表的
FragmentActivity

以下是我的
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();
}
My
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, 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());
    }
}
现在事情是这样的:

当我使用后退键退出应用程序,然后通过图标再次打开它时;即使它保存在内存中,列表也会自动重新创建:因此我在同一视图中获得了两个联系人列表

savedInstanceState
在这种情况下为空,因此达到了if条件,但实际上视图中已经有我以前的联系人列表。有什么好处?如何避免重新创建列表?我已经尝试过使用实例变量,但是没有用


我还希望避免100%地重新创建列表-如果我可以重用现有视图,太棒了。

首先,您的savedInstanceState为空的原因是-系统只保存由于系统约束而被销毁的活动的状态。如果您退出某个活动,它将被永久销毁,并且不会保存任何状态

相关文件:

当您的活动因用户按Back键或 活动自行完成,系统对该活动的概念 实例将永远消失,因为该行为指示该活动 不再需要了。但是,如果系统由于 到系统约束(而不是正常的应用程序行为),然后 实际的活动实例消失了,系统会记住它 存在,因此如果用户导航回它,系统将创建 使用一组保存的数据创建活动的新实例 描述活动被销毁时的状态

所以,您的特殊问题似乎是,当您的活动消失时,您的静态HumanContact类仍在内存中,而您的新活动正在加载另一个联系人副本

有几种方法可以解决这个问题。首先,您可以在HumanContent上实现一个方法来清除其所有项,并在启动活动的新实例时调用它。这有助于确保您的数据是最新的,但也意味着您必须重新加载联系人

其次,如果您想真正避免重新加载数据,我建议为联系人创建某种独立于活动的缓存。您应该将您的活动视为相当短暂的,它可以并且将被频繁地破坏和重新创建,而缓存可以持久。 在某种程度上,HumanContent似乎已经填补了这一职责。您正在使用它来存储数据,并且它将在活动的生命周期之外持续存在。您还可以向它添加一个方法,检查它是否加载了联系人,如果没有,则自行加载联系人。通过这种方式,它可以完全控制数据的加载和缓存,活动可以单独负责数据的显示。使用这种类型的解决方案时要小心,不要在内存中存储太多数据,要在预期数据发生更改时随时重新加载缓存,并且要注意,在某些情况下,系统可能会重新启动进程,因此缓存必须准备好重新加载数据,以防数据被破坏


至于保存视图,如果用户退出您的活动,那么将调用finish(),并且您的活动将被销毁。请记住,在这种情况下,系统不再具有任何活动概念,因此将无法保留这些视图以供重用。

始终建议使用缓存来保留数据。正如Groucho提到的,你可以选择存储选项 查看下面的链接了解详细信息


在displayContacts()中加载完数据后,您可以在共享首选项中保存一个标志(显示的联系人)。在onCreate()中检查首选项值,并相应地调用displayContacts()

我们有如上所述的现有方法。如果您发现自己在使用时遇到困难,那么您可以尝试以下方法:-

  • 使用false初始化布尔值
  • 获取数据后,将该布尔值设置为true
  • 现在,在重新启动OnCreate()时,检查布尔值是否为true或false。如果为false,则需要再次提取该数据,否则不需要获取该数据。为相同的设置条件

    • 我曾经遇到过类似的问题。我不确定这是否合法,但我使用的代码如下,它修复了很多问题:

      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;
          }
      
      您可以调整
      沉降充气(充气机)方法与您的方法。
      神奇之处在于名为
      view1
      的静态变量。一旦片段被初始化,它就会充满数据。片段的其他实例将简单地从其前父对象中撕裂
      view1
      ,并将其粘贴到自身上


      由于对象保存在ram中,所以文件存储缓存速度非常快。如果操作系统垃圾收集对象,静态变量将再次为空,并且在重新创建视图时不会出现重复项。

      这很简单。在活动中遵循以下步骤

      • 在活动类中声明列表视图对象和列表视图适配器对象
      • 在OnCreate()方法中初始化listview对象listview_适配器对象,并在displayContacts()中添加内容

      那么您肯定不会得到内容复制。

      您无法停止执行
      onCreate
      函数。但是,您可以应用变通方法以避免重复列表,您可以从listview中删除所有项,然后让它重新填充listview

      @Override
      public void onPause ()
      {
          super.onPause();
          //...........
      }
      
      @Override
      public void onStop ()
      {
          super.onPause();
          //............
      }
      
      检查是否可以在片段中使用这些方法?
      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);
      }
      
      if(yourcomponent==null) {
          initializecomponent();
      }