简体   繁体   English

放置和获取saveInstanceState数据

[英]Putting and getting savedInstanceState data

I'm just trying to understand the Activity lifetime with this simple example by trying to find how I get back the SomeIntegers g_values object and the ArrayList AnInteger objects within it. 我只是通过尝试查找如何获取其中的SomeIntegers g_values对象和ArrayList AnInteger对象的简单示例,来了解Activity的生命周期。

As it is, it is not of much meaning but will serve as a paradigm of my real situation where initial setup requires the app to schlepp through countless reams of pre-processing eg access and list fonts, analyse all my available games, in the APK, on file and online in my website, players records etc. The final app is a system of games and activities to help SpLD (dyslexia) students of all ages exercise their reading, spelling, organisational skills and short term memory. 实际上,它没有多大意义,但可以作为我实际情况的范例,在该情况下,初始设置需要应用程序通过无数次预处理(例如访问和列出字体),在APK中分析我所有可用的游戏来进行schlepp (在文件上以及在我的网站上在线记录的球员记录等)。最终的应用程序是一个游戏和活动系统,可以帮助各个年龄段的SpLD(阅读障碍)学生锻炼他们的阅读,拼写,组织能力和短期记忆。 It is of serious intent. 这是认真的意图。 Although free running, it is best used with SpLD supervisors/tutors who can set the work schedule of their charge and even add their own games. 尽管可以免费运行,但最好与SpLD主管/辅导员一起使用,他们可以设置负责的工作时间表,甚至添加自己的游戏。

Anyway enough of the irrelevant background. 无论如何,无关紧要的背景。

Can I save my somewhat complex objects using access to the savedInstanceState (somewhat hampered by their being no putxxxxx method of the correct form) or should abandon this approach and recover the data from persistent files or databases? 我可以使用对saveInstanceState的访问来保存我有些复杂的对象(由于没有正确形式的putxxxxx方法而使它们受阻)还是应该放弃这种方法并从持久性文件或数据库中恢复数据? This can be discussed hopefully within the limits of this simple example, the real thing is simply more of the same but with different details. 可以希望在这个简单示例的范围内对此进行讨论,而实际情况更是如此,只是细节不同。

Note added after. 注意后添加。 There is also the issue of taking the user/player back to where he/she was when the app experienced the need to save its InstanceState. 还有一个问题,当应用程序需要保存其InstanceState时,会将用户/播放器带回他/她所在的位置。 As the major influence seems to be the orientation of the tablet, I could maybe side step that by locking the orientation at start up. 由于主要的影响似乎是平板电脑的方向,我也许可以通过在启动时锁定方向来避开它。 This would simplify many display issues also but is it an "unacceptable" style? 这样也可以简化许多显示问题,但这是“不可接受的”样式吗?

import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class TestBundle extends AppCompatActivity {
    SomeIntegers g_values;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.out.println("onCreate (" + (savedInstanceState == null ? "null)" : "set)"));
        if (savedInstanceState == null)
        {   g_values = new SomeIntegers();
            String result = g_values.report();
            System.out.println("Startup Result: " + result);
            setContentView(R.layout.activity_test_bundle); // Where do I put this line?
        }
        else
        {   //Do I get g_values back here?
            //More relevantly, can I, and how can I, put g_values in the
            //savedInstanceState when onSaveInstanceState is called?
            String result = g_values.report();
            System.out.println("Result: " + result);
        }
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        System.out.println("onSaveInstanceState (" + (outState == null ? "null)" : "set)"));
        //How do I add g_values to the Bundle?
    }
    // Following is just stuff to watch the progress of the
    // Activity in the ADB Log. Not of much relevance. Or is it?
    @Override
    protected void onStop() {
        super.onStop();
        System.out.println("onStop()");
    }
    @Override
    protected void onStart() {
        super.onStart();
        System.out.println("onStart()");
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        System.out.println("onRestart()");
    }
    @Override
    protected void onResume() {
        super.onResume();
        System.out.println("onResume()");
    }
    @Override
    protected void onPause() {
        super.onPause();
        System.out.println("onPause()");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("onDestroy()");
    }
}

public class SomeIntegers {
    private ArrayList<AnInteger> c_values;
    SomeIntegers() {
        c_values = new ArrayList<AnInteger>();
        c_values.add (new AnInteger(1));
        c_values.add (new AnInteger(2));
        c_values.add (new AnInteger(3));
        c_values.add (new AnInteger(4));
        c_values.add (new AnInteger(29));
        c_values.add (new AnInteger(30));
    }
    String report() {
        String g = "";
        for (AnInteger ai  : c_values) {
            if (!g.isEmpty()) g = g + ", ";
            g = g + ai.getC_value();
        }
        return (g.isEmpty() ? "Empty" : g);
    }
}
public class AnInteger {
    private int c_value;
    AnInteger(int value) { c_value = value); }
    public int getC_value () { return c_value; }
}

Thank you. 谢谢。 Josie Hill 乔西·希尔

The concept of restoring the activity states is based on device orientation. 恢复活动状态的概念基于设备方向。 So for example if you pull some changes from persisted file, loaded it, when the screen changes it angle of rotation that data will be recreated. 因此,例如,如果您从持久性文件中提取一些更改,然后将其加载,则当屏幕更改其旋转角度时,将重新创建数据。 So the activity uses a bundle to wrap that data, and permits the user to save the current working state of such file, which then can be restored. 因此,活动使用捆绑包包装该数据,并允许用户保存该文件的当前工作状态,然后可以将其还原。 Here is a great link . 这是一个很好的链接 Your requirements sounds consistent as it regards data changes, as per my first question regarding the anticipated file sizes, your requirements sounds relatively small. 关于数据更改,您的要求听起来是一致的。根据我关于预期文件大小的第一个问题,您的要求听起来相对较小。

To work compound data types and abstract data types , do consider using GSON.which is a Java serialization/deserialization library to convert Java Objects into JSON and back 要处理复合数据类型和抽象数据类型,请考虑使用GSON.GSON。这是一个Java序列化/反序列化库,可以将Java对象转换为JSON并返回

Therefore I can recommend you using the power of shared preferences in android.If you have a relatively small collection of key-values that you'd like to save, you should use the SharedPreferences APIs. 因此,我建议您使用android中共享首选项的功能。如果您要保存的键值集合相对较小,则应使用SharedPreferences API。 A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. 一个SharedPreferences对象指向一个包含键-值对的文件,并提供读取和写入它们的简单方法。 In simple terms,Shared Preferences allow you to save and retrieve data in the form of key,value pair. 简而言之,共享首选项允许您以键,值对的形式保存和检索数据。

Android provides many ways of storing data of an application. Android提供了多种存储应用程序数据的方式。 If your requirements needs storage consistency, I would go with the database approach, I would recommend using realm.Realm is a mobile database and a replacement for SQLite. 如果您的需求需要存储一致性,那么我会采用数据库方法,建议使用realm。Realm是移动数据库,是SQLite的替代品。 Although is an OO database it has some differences with other databases. 尽管是OO数据库,但它与其他数据库有一些区别。 Realm is not using SQLite as it's engine. Realm并未使用SQLite作为引擎。 Instead it has own C++ core and aims to provide a mobile-first alternative to SQLite. 相反,它具有自己的C ++内核,旨在提供SQLite的移动优先方法。

Hope this was helpful:) 希望这对您有所帮助:)

First make your data models implement Parcelable : 首先,使您的数据模型实现Parcelable

AnInteger: AnInteger:

public class AnInteger implements Parcelable {
    private int c_value;

    public AnInteger(int value) {
        this.c_value = value;
    }

    public int getC_value() {
        return c_value;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.c_value);
    }

    protected AnInteger(Parcel in) {
        this.c_value = in.readInt();
    }

    public static final Parcelable.Creator<AnInteger> CREATOR = new Parcelable.Creator<AnInteger>() {
        @Override
        public AnInteger createFromParcel(Parcel source) {
            return new AnInteger(source);
        }

        @Override
        public AnInteger[] newArray(int size) {
            return new AnInteger[size];
        }
    };
}

SomeIntegers: SomeIntegers:

public class SomeIntegers implements Parcelable {
    private ArrayList<AnInteger> c_values;

    public SomeIntegers() {
        c_values = new ArrayList<>();
        c_values.add(new AnInteger(1));
        c_values.add(new AnInteger(2));
        c_values.add(new AnInteger(3));
        c_values.add(new AnInteger(4));
        c_values.add(new AnInteger(29));
        c_values.add(new AnInteger(30));
    }

    public String report() {
        String g = "";
        for (AnInteger ai : c_values) {
            if (!g.isEmpty()) {
                g = g + ", ";
            }
            g = g + ai.getC_value();
        }
        return (g.isEmpty() ? "Empty" : g);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeTypedList(this.c_values);
    }

    protected SomeIntegers(Parcel in) {
        this.c_values = in.createTypedArrayList(AnInteger.CREATOR);
    }

    public static final Parcelable.Creator<SomeIntegers> CREATOR = new Parcelable.Creator<SomeIntegers>() {
        @Override
        public SomeIntegers createFromParcel(Parcel source) {
            return new SomeIntegers(source);
        }

        @Override
        public SomeIntegers[] newArray(int size) {
            return new SomeIntegers[size];
        }
    };
}

Then in your activity saving and restoring gets pretty easy, here is an example using your current data model: 然后,在活动中保存和恢复变得非常容易,这是一个使用当前数据模型的示例:

//set up class fields/members
private final static String STATE_G_VALS = "STATE_G_VALS";
SomeIntegers g_values = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test_bundle);
    System.out.println("onCreate (" + (savedInstanceState == null ? "null)" : "set)"));
    if (savedInstanceState != null) {
        // get g_values back here
        g_values = savedInstanceState.getParcelable(STATE_G_VALS);
    }

    if (g_values == null) {
        // ok its null, lets make one
        g_values = new SomeIntegers();
    }
    // log some stuff
    String result = g_values.report();
    System.out.println("Result: " + result);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
    //set g_values to the Bundle/saved state (even if it is null)
    outState.putParcelable(STATE_G_VALS, g_values);
    super.onSaveInstanceState(outState);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM