Android ViewModel 不断初始化 ArrayList
Posted
技术标签:
【中文标题】Android ViewModel 不断初始化 ArrayList【英文标题】:Android ViewModel keeps initialising ArrayList 【发布时间】:2019-02-27 02:00:02 【问题描述】:在过去的两天里,我一直在尝试使用 ViewModel 来存储 ArrayList。但是,每次我访问 ViewModel 时,它都会初始化 ArrayList,删除其中存储的数据。
我尝试在 ViewModel 中包含方法来控制 ArrayList 的初始化,但没有帮助。每次访问 ViewModel 时,它都会将 ArrayList 重置为“null”。
为什么会发生这种情况,我该如何阻止它?
ViewModel_Quiz.java
import android.arch.lifecycle.ViewModel;
import java.util.ArrayList;
public class ViewModel_Quiz extends ViewModel
ArrayList<String> checkboxStatus;
public void sendCheckboxStatus(ArrayList<String> arrayList)
checkboxStatus = arrayList;
public ArrayList<String> getCheckboxStatus()
return checkboxStatus;
FragmentQuiz_Selection.java
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.support.constraint.Group;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
public class FragmentQuiz_Selection extends Fragment implements View.OnClickListener
private FloatingActionButton fab_start;
//Create member variable for Checkbox loops
private boolean mChecked;
//Create ArrayList for QuizSelection
private ArrayList<String> mQuizSelection = new ArrayList<>();
//Create boolean for Expand/Collapse
//boolean iv_group_instruments = false;
//Create View variable
private View mView;
//Variables for database
private SQLiteDatabase mInstrumentsDB;
private InstrumentsDbHelper instrumentsDb;
//This contains the same data as mQuizSelection. It's used to prepare the database and populate mTotalRows.
private String[] mQuizSelectionArray;
//This is used as part of quizPrep() to populate mTotalRows. This may note need to be a memberVariable.
private int mTotalRows;
//This contains the total number of columns for the user's selection.
private int mTotalColumns;
//This holds all of the column/row pairs for the quiz.
private ArrayList<String> mQuizList = new ArrayList<>();
//This variable is used to interface with MainActivity
private OnQuizStarted mCallback;
//This ArrayList holds the CheckBox status for restoring the user's state
private ArrayList<String> mCheckboxStatus = new ArrayList<>();
public static FragmentQuiz_Selection newInstance()
FragmentQuiz_Selection fragment = new FragmentQuiz_Selection();
return fragment;
//Create an interface to communicate with MainActivity
public interface OnQuizStarted
void onQuizStarted (ArrayList<String> arrayList);
// Connect the interface to MainActivity
@Override
public void onAttach(Context context)
super.onAttach(context);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try
mCallback = (OnQuizStarted) context;
catch (ClassCastException e)
throw new ClassCastException(context.toString()
+ " must implement OnQuizStarted");
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
//Store views in variable
mView = inflater.inflate(R.layout.fragment_quiz_selection, container, false);
// Set onClickListeners
setOnClickListeners();
//Ensure all Checkboxes are set to 'false'
ViewGroup constraintLayout = (ViewGroup) mView.findViewById(R.id.quiz_menu_layout);
loopCheckboxesFalse(constraintLayout);
//Create onClickListener for 'start' FAButton
fab_start.setOnClickListener(new View.OnClickListener()
//If you click the FAButton, start the Quiz
@Override
public void onClick(View view)
//Create variable for ConstraintLayout
ViewGroup constraintLayout = (ViewGroup) mView.findViewById(R.id.quiz_menu_layout);
quizStart(constraintLayout);
);
return mView;
//Handle actions when the user is returning to the Fragment
@Override
public void onResume()
super.onResume();
Log.i("LIFECYCLE CHANGE", "Quiz_Selection, onResume has been called!");
//Get mCheckboxStatus from ViewModel
ViewModel_Quiz viewmodel = ViewModelProviders.of(this).get(ViewModel_Quiz.class);
if (viewmodel.getCheckboxStatus() != null && !(viewmodel.getCheckboxStatus().isEmpty()))
mCheckboxStatus = viewmodel.getCheckboxStatus();
setCheckboxStatus(mCheckboxStatus);
//If mChecked is 'true,' show FAButton. If mChecked is 'false,' hide FAButton.
ViewGroup layout = mView.findViewById(R.id.quiz_menu_layout);
mChecked = loopCheckboxesBoolean(layout);
fabButton(mChecked, fab_start);
//Handle actions when the user is leaving, but not necessarily destroying, the Fragment
@Override
public void onPause()
super.onPause();
Log.i("LIFECYCLE CHANGE", "Quiz_Selection, onPause has been called!");
mCheckboxStatus.clear();
recordCheckboxStatus(mCheckboxStatus);
//Send mCheckboxStatus to ViewModel
ViewModel_Quiz viewmodel = ViewModelProviders.of(this).get(ViewModel_Quiz.class);
viewmodel.sendCheckboxStatus(mCheckboxStatus);
@Override
public void onClick(View view)
if (view instanceof CheckBox)
onCheckboxClicked(view);
else if (view instanceof ImageView)
onExpandCollapse(view);
//METHOD: Set Checkbox status for 'onCreate'
private void setCheckboxStatus (ArrayList<String> arrayList)
ViewGroup layout = mView.findViewById(R.id.quiz_menu_layout);
int childCount = layout.getChildCount();
//Iterate through the layout's CheckBox views
for (int i = 0; i < childCount; i++)
View view = layout.getChildAt(i);
//If item is a Checkbox, assign it as true or false
if (view instanceof CheckBox)
if (arrayList.get(0) == "y")
((CheckBox) view).setChecked(true);
arrayList.remove(0);
else if (arrayList.get(0) == "n")
((CheckBox) view).setChecked(false);
arrayList.remove(0);
//METHOD: Store Checkbox status for 'onPause'
private void recordCheckboxStatus (ArrayList<String> arrayList)
ViewGroup layout = mView.findViewById(R.id.quiz_menu_layout);
int childCount = layout.getChildCount();
//Iterate through the layout's views
for (int i = 0; i < childCount; i++)
View view = layout.getChildAt(i);
//If item is a Checkbox && Checkbox is 'checked,' add 'y' to the arrayList.
if (view instanceof CheckBox && ((CheckBox) view).isChecked())
arrayList.add("y");
//Else if item is a Checkbox && Checkbox is 'not checked,' add 'n' to the arrayList.
else if (view instanceof CheckBox && !((CheckBox) view).isChecked())
arrayList.add("n");
//Else if item is not a Checkbox, skip this view and move to the next one
else
【问题讨论】:
不是对您的具体问题的直接回答,但我建议在像这样使用ViewModel
时使用LiveData
。以下有更多信息,包括在 ViewModel 中使用它 - developer.android.com/topic/libraries/architecture/livedata
谢谢。你能解释一下为什么我在以这种方式使用 ViewModel 时应该使用 LiveData 吗?
【参考方案1】:
你必须在你的 ViewModel 中使用 MutableLiveData。
import android.arch.lifecycle.ViewModel;
import java.util.ArrayList;
public class ViewModel_Quiz extends ViewModel
MutableLiveData<Arraylist<String>> checkboxStatus;
public void sendCheckboxStatus(ArrayList<String> arrayList)
checkboxStatus.postValue(arrayList);
public ArrayList<String> getCheckboxStatus()
return checkboxStatus;
【讨论】:
以上是关于Android ViewModel 不断初始化 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android/Kotlin App 上通过 Koin 注入在 BaseActivity 中初始化/注入通用 ViewModel
在android中使用“by viewModels()”与“ViewModelProvider(this).get(ViewModel::class.java)”进行视图模型初始化