如何避免在Android上重新创建视图的onCreate? [英] How to avoid recreating view on onCreate on Android?

查看:161
本文介绍了如何避免在Android上重新创建视图的onCreate?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a FragmentActivity that shows a contacts list.

下面是我的的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 以防万一:

And I'm not sure if this is relevant, but here's 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());
    }
}

现在这里的东西:

当我使用返回键退出应用程序,然后通过图标再次打开它;列表中重新创建本身,即使它被保存在内存中。所以我得到了同样的看法接触的双榜

When I use the back key to exit the application, and then open it again via the icon; the list recreates itself even though it is saved in memory: so I get a double list of contacts on the same view.

savedInstanceState 是在这种情况下空,因此达到if条件,但在现实的看法已经有了我的previous联系人列表。怎么办?我怎样才能避免重新创建列表?我已经尝试过使用实例变量来代替,但无济于事。

savedInstanceState is null in that case, so the if condition is reached, but in reality 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.

我也想避免重现时代的名单100% - 如果我可以重用现有视图,真棒

I'd also like to avoid recreating the list 100% of the times - if I can reuse the existing view, awesome.

推荐答案

首先,你savedInstanceState是空的原因 - 该系统只保存了那些由于系统限制破坏活动状态。如果你背出一个Activity被销毁的好,没有状态将被保存。

First, the reason your savedInstanceState is null - The system only saves state of activities that are destroyed due to system constraints. If you back out of an Activity it is destroyed for good, and no state will be saved.

相关文档: <一href="http://developer.android.com/training/basics/activity-lifecycle/recreating.html">http://developer.android.com/training/basics/activity-lifecycle/recreating.html

当你的活动是因为用户presses破坏返回或   活动结束本身,即活动的系统的概念   实例已经一去不复返了,因为行为表明活动   不再需要。然而,如果系统破坏,由于该活动   系统的限制(而不是正常的应用程序的行为),那么尽管   实际活动情况已经一去不复返了,系统会记住它   存在这样如果用户返回到它,系统会创建   活动的使用一组保存的数据的一个新实例   介绍活动的,当它被摧毁的状态。

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.

所以,好像你特别的问题是,当你的活动已经一去不复返了,你的静态HumanContact类仍然在内存中,新的活动与您的联系人另一个副本加载它。

So, it seems like your particular problem is that while your Activity is gone, your static HumanContact class is still in memory, and your new Activity is loading it with another copy of your contacts.

有几种方法可以解决这个问题。首先,你可以实现在HumanContent的方法来清除所有的项目,并调用它,只要你启动您的活动的一个新实例。这将对确保您的数据是最新的好处,但也意味着你必须重新载入你的联系人。

There are a couple ways you could solve this. First, you could implement a method on HumanContent to clear out all its items, and call it whenever you launch a new instance of your Activity. This would have the benefit of ensuring your data is up to date, but would mean you have to reload your contacts.

其次,如果你想真正避免重新加载数据,我建议建立某种形式的缓存为独立于活动的联系人。你应该考虑你的活动是相当短暂的,它可以和将被销毁并重新创建频繁,而缓存可以持续。

Secondly, if you wanted to truly avoid reloading the data, I'd recommend creating some sort of cache for the contacts that is independent of the Activity. You should consider your Activity as fairly transient, it can and will be destroyed and recreated frequently, whereas a cache can persist.

HumanContent似乎已经填补这一责任,在一定程度上。你用它来存储数据,并且它持续超出你的活动的生命周期。可以一种方法附加地添加到它来检查,​​看它是否具有接触加载,如果不是加载它们本身。这样,它完全控制加载和缓存数据,并且活动可以专门负责该数据的显示。小心这种类型的解决方案,你不能存储太多的数据在内存中,你发现你重装你希望你的数据已经改变缓存任何时间,要知道,你的进程可能被系统在某些情况下重新启动,因此缓存必须ppared重新加载的情况下,它被破坏你的数据$ P $。

HumanContent seems to be filling this responsibility already, to an extent. You're using it to store your data, and it is persisting beyond the lifecycle of your Activity. You could additionally add a method to it that checks to see if it has contacts loaded, and if not loads them itself. This way it has complete control over loading and caching your data, and Activities can be responsible solely for the display of this data. Be careful with this type of solution that you're not storing too much data in memory, that you're reloading your cache anytime you expect your data to have changed, and be aware that your process might be restarted by the system in some cases, so your cache must be prepared to reload your data in case it is destroyed.

至于preserving你的意见,如果用户打了退堂鼓的活动的话,完成()被调用,你的活动将被销毁。请记住,在此情况下,系统不再具有活性的任何概念,所以就没有办法preserve这些意见,供重复使用。

As for preserving your Views, if the user is backing out of your Activity then the finish() is being called, and your Activity is going to be destroyed. Remember, in this case the system no longer has any concept of the Activity, so there will be no way to preserve these views for reuse.

这篇关于如何避免在Android上重新创建视图的onCreate?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆