简体   繁体   中英

android SaveInstance in activity and garbage collector

Currently I am working on the second version of my vocabulary app. The first version does not provide as much documentation to expand the application. so I decided to start from the ground up.

I have an activity, every time I send it to background and then get it back to foreground, some objects became null and activity restarts. In onResume, I logged the value of the null object.

The old activity (version 1) does not have that problem.

I tried avoid that null problem whilst saving activities states and objects to SaveInstanceState and restore them. but RestoreInstance was never called.

here is my code

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_query);


    Log.e(TAG, "onCreate");

    /* Initialize DATA */
    data = new DataHandler(this);


    /* Initialize VIEWS */
    btnPhase  = findViewById(R.id.query_voc_phase);
    cardPath  = findViewById(R.id.query_voc_path);
    queryView = findViewById(R.id.query_view);
    btnShow   = findViewById(R.id.query_btn_show_answer);
    btnRight  = findViewById(R.id.query_btn_mark_right);
    btnWrong  = findViewById(R.id.query_btn_mark_wrong);
    btnNext   = findViewById(R.id.query_btn_show_next);
}

@Override
protected void onStart() {
    super.onStart();

    Log.e(TAG, "onStart");
    /* set OnClickListener */
    btnShow.setOnClickListener(this);
    btnRight.setOnClickListener(this);
    btnWrong.setOnClickListener(this);
    btnNext.setOnClickListener(this);


    //init Variables
    queryList       = new ArrayList<>();
    idList           = new ArrayList<>();
    listGroupings   = new ArrayList<>();
    answeredList    = new ArrayList<>();


    //init Preferences
    preferences = PreferenceManager.getDefaultSharedPreferences(this);

    //set Visibility of view items based on Preferences
    if (!preferences.getBoolean(Preferences.SHOW_CARD_PATH_ENABLED, true))
        cardPath.setVisibility(View.GONE);

    //load preferences
    userID = preferences.getInt(Preferences.CURRENT_USER, -1);

    //check if flashing card is enabled and get time
    flash_time = preferences.getBoolean(Preferences.FLASH_CARD_ENABLED, false) ? preferences.getInt(Preferences.FLASH_TIME, flash_time) : -1;


    //get data from intent
    Intent intent = getIntent();
    if (intent.hasExtra(QUERY_CONTAINER_LIST)) {
        //get data into the list
        HashMap<String, ArrayList<Integer>> queryData = data.getCardsToQuery(intent.getStringArrayListExtra(QUERY_CONTAINER_LIST));

        idList = queryData.get("iList");
        listGroupings = queryData.get("listGroupings");
    }


    // change active Fragment to initial fragment
    changeFragment(QueryViews.Simple);
}

@Override
protected void onResume() {
    super.onResume();

    Log.e(TAG, "onResume");
    Log.e(TAG, "current card is null " + (currentCard == null));

    //loads a new card if there is none
    if(currentCard == null) loadNext();
}

/*
    InstanceState
 */

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    Log.e(TAG, "RESTORE");

    queryList = savedInstanceState.getParcelableArrayList("queryList");
    idList = savedInstanceState.getIntegerArrayList("iList");
    listGroupings = savedInstanceState.getIntegerArrayList("listGroupings");
    answeredList = savedInstanceState.getParcelableArrayList("answeredList");

    currentCard = (VocabularyCard)savedInstanceState.getSerializable("currentCard");
    lastCard =  (VocabularyCard)savedInstanceState.getSerializable("lastCard");
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    Log.e(TAG, "SAVE");

    outState.putParcelableArrayList("queryList", queryList);
    outState.putIntegerArrayList("idList", idList);
    outState.putIntegerArrayList("listGroupings", listGroupings);
    outState.putParcelableArrayList("answeredList", answeredList);

    outState.putParcelable("currentCard", currentCard);
    outState.putParcelable("lastCard", lastCard);

    super.onSaveInstanceState(outState);
}

Spotting below error, maybe it is a typo error, but may be the culprit of your null object issue. You restore iList inside onRestoreInstanceState ,

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    Log.e(TAG, "RESTORE");

    idList = savedInstanceState.getIntegerArrayList("iList");

}

But inside onSaveInstanceState , you put idList ,

@Override
protected void onSaveInstanceState(Bundle outState) {
    Log.e(TAG, "SAVE");

    ...
    outState.putIntegerArrayList("idList", idList);
    ...

    super.onSaveInstanceState(outState);
}

I found a solution. I found out that onRestoreInstanceState will called if device rotates. First of all if something became null, you should first check if the object was assigned a value. in this case i overlooked, that the object was never assigned a value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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