java—如何最好地实现viewmodel(在androidx中)使数据在配置更改后仍然有效

sg24os4d  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(369)

我尝试在androidx中实现一个recyclerview的viewmodel体系结构,遵循在这里输入link description和在这里输入link description中所述的示例。recyclerview中的项目在单击位置时被选中,但由于某些原因,在设备旋转和配置更改后,所选项目取消选择并恢复为默认值。我知道过去有过这样的问题的答案,但我所看到的不是直接适用于我的情况,就是只适用于不赞成的情况。
有人能告诉我我做错了什么吗!
以下是我的代码片段:
已添加依赖项

dependencies {

def lifecycle_version = "2.2.0"

// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"

// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"

// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"

// Annotation processor
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"

implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'

}
repository类:公共类topicrepository{

private Application application;
private SharedPreferences sharedPreferences;
private ArrayList<RootTopic> topicGroupList;
private MutableLiveData<ArrayList<RootTopic>>topicGroupMLD;

public TopicRepository(Application application) {
    this.application = application;

}

public LiveData<ArrayList<RootTopic>> getRootTopicLD(String subject){
    if (topicGroupMLD == null){
        topicGroupMLD = new MutableLiveData<ArrayList<RootTopic>>();
        generateTopicGroup(subject);
    }
        return topicGroupMLD;
}

private void generateTopicGroup(final String subject){
    Log.d(TAG, "generateTopicGroup: CALLED");
    isRequestingMLD.postValue(true);
    final String subjectTopicGroupList = subject + "TopicGroupList";

    sharedPreferences = application.getSharedPreferences(AppConstant.Constants.PACKAGE_NAME, Context.MODE_PRIVATE);
    String serializedTopicGroup = sharedPreferences.getString(subjectTopicGroupList, null);
     if (serializedTopicGroup != null){

         Gson gson = new Gson();
         Type type = new TypeToken<ArrayList<RootTopic>>(){}.getType();
         topicGroupList = gson.fromJson(serializedTopicGroup, type);
         topicGroupMLD.postValue(topicGroupList);

     }else {//       - Not saved in SP

         Log.d(TAG, "getTopicGroup: NOT IN SP");
         new ActiveConnectionCheck(new ActiveConnectionCheck.Consumer() {
             @Override
             public void accept(Boolean internet) {
                 Log.d(TAG, "accept: CHECKED INTERNET");
                 if (internet){
                     Log.d(TAG, "accept: INTERNET CONNECTION = TRUE");
                     internetCheckMLD.postValue(AppConstant.Constants.IS_INTERNET_REQUEST_SUCCESS);

                     FirebaseFirestore fbFStore = FirebaseFirestore.getInstance();
                     CollectionReference lectureRef = fbFStore.collection(subject);
                     lectureRef.orderBy(AppConstant.Constants.POSITION, Query.Direction.ASCENDING)
                             .get().addOnSuccessListener(
                             new OnSuccessListener<QuerySnapshot>() {
                                 @Override
                                 public void onSuccess(QuerySnapshot queryDocumentSnapshots) {

                                     ArrayList<Topic>topicList = new ArrayList<>();
                                     ArrayList<String> rootTitleList = new ArrayList<>();

                                     for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots){
                                         Topic topic = snapshot.toObject(Topic.class);
                                         topicList.add(topic);
                                     }

                                     Log.d(TAG, "onSuccess: TopicListSize = " + topicList.size());

                                     for (Topic topic : topicList){
                                         String rootTopicString = topic.getRootTopic();
                                         if (!rootTitleList.contains(rootTopicString)){
                                             rootTitleList.add(rootTopicString);
                                         }
                                     }

                                     Log.d(TAG, "onSuccess: RootTitleListSize = " + rootTitleList.size());

                                    for (int x = 0; x < rootTitleList.size(); x ++){
                                        RootTopic rootTopic = new RootTopic(rootTitleList.get(x), new ArrayList<Topic>());
                                        topicGroupList = new ArrayList<>();
                                        topicGroupList.add(rootTopic);
                                    }

                                     for (int e = 0; e < topicList.size(); e++){
                                         addTopicToGroup(topicGroupList, topicList.get(e));
                                     }

                                     topicGroupMLD.postValue(topicGroupList);
                                     Gson gson = new Gson();
                                     String serializedTopicGroup = gson.toJson(topicGroupList);
                                     sharedPreferences.edit().putString(subjectTopicGroupList, serializedTopicGroup).apply();

                                     Log.d(TAG, "onSuccess: TOPICGROUPSIZE = " + topicGroupList.size());
                                     Log.d(TAG, "onSuccess: SERIALIZED GROUP = " + serializedTopicGroup);
                                     isRequestingMLD.postValue(false);

                                 }
                             }
                     ).addOnFailureListener(
                             new OnFailureListener() {
                                 @Override
                                 public void onFailure(@NonNull Exception e) {
                                     isRequestingMLD.postValue(false);
                                     Log.d(TAG, "onFailure: FAILED TO GET TOPICLIST e = " + e.toString());
                                 }
                             }
                     );

                 }else {
                     internetCheckMLD.postValue(AppConstant.Constants.IS_INTERNET_REQUEST_FAIL);
                     Log.d(TAG, "accept: InternetCONECTION = " + false);
                 }
             }
         });

     }

}

private void addTopicToGroup(ArrayList<RootTopic>rootGroup, Topic topic){
    for (int x = 0; x < rootGroup.size(); x++){
        RootTopic rootTopic = rootGroup.get(x);
        if (rootTopic.getRootTopicName().equals(topic.getRootTopic())){
            rootTopic.getTopicGroup().add(topic);
        }
    }
}

}
我的viewmodel类

public class LectureViewModel extends AndroidViewModel {

public static final String TAG = AppConstant.Constants.GEN_TAG + ":LectureVM";

private Application application;
private TopicRepository topicRepository;
private ArrayList<RootTopic> topicGroupList;

public LectureViewModel(@NonNull Application application) {
    super(application);
    this.application = application;
    topicRepository = new TopicRepository(application);

}

public LiveData<ArrayList<RootTopic>> getRootTopicListLD(String subject){

    return topicRepository.getRootTopicLD(subject);
}

}
活动实现viewmodel

public class LectureRoomActivity extends AppCompatActivity {

public static final String TAG = AppConstant.Constants.GEN_TAG + " LecRoom";
private LectureViewModel lectureRoomVM;
private String subject;
private RecyclerView mainRecyclerView;

private RootTopicAdapter rootTopicAdapter;

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

    Intent intent = getIntent();
    subject = intent.getStringExtra(AppConstant.Constants.SUBJECT);

    mainRecyclerView = findViewById(R.id.recyclerView);

    downloadVM = new ViewModelProvider(this).get(DownloadLectureViewModel.class);
    lectureRoomVM = new ViewModelProvider(this).get(LectureViewModel.class);
    lectureRoomVM.getRootTopicListLD(subject).observe(
            this,
            new Observer<ArrayList<RootTopic>>() {
        @Override
        public void onChanged(ArrayList<RootTopic> rootTopics) {
            if (rootTopics != null){
                currentTopic = lectureRoomVM.getCursorTopic(subject, rootTopics);
                setUpRec(rootTopics, currentTopic);
            }
        }
    });

}

private void setUpRec( ArrayList<RootTopic>topicGroup, CursorTopic currentTopic){
     rootTopicAdapter = new RootTopicAdapter(topicGroup,
            new ArrayList<String>(), currentTopic.getParentPosition(),
            currentTopic.getCursorPosition());

    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(
            this, RecyclerView.VERTICAL,false);

    mainRecyclerView.setHasFixedSize(true);
    mainRecyclerView.setLayoutManager(linearLayoutManager);
    mainRecyclerView.setAdapter(rootTopicAdapter);

    Log.d(TAG, "setUpRec: SETTING REC");
}

}

dvtswwa3

dvtswwa31#

为了保存和恢复与ui相关的数据,最好使用savedinstancestate bundle在最后一个状态下生存。要实现这一点,只需重写ui活动中的两个方法。请参见下面的示例代码段。
在你的根主题适配器里

// Add this where you detect the item click, probably in your adaptor class
private int lastRecyclerViewIndex; // define the variable to hold the last index
...

@Override
public void onClick(View v) {
    lastRecyclerViewIndex = getLayoutPosition();
}

public int getLastIndex() {
    return lastRecyclerViewIndex;
}

在视图模型类中

public class LectureViewModel extends AndroidViewModel {

    public static final String TAG = AppConstant.Constants.GEN_TAG + ":LectureVM";

    private Application application;
    private TopicRepository topicRepository;
    private ArrayList<RootTopic> topicGroupList;
    public boolean mustRestore; // Is there any data to restore
    public int lasIndexSelected;

    public LectureViewModel(@NonNull Application application) {
        super(application);
        this.application = application;
        topicRepository = new TopicRepository(application);

    }

    public LiveData<ArrayList<RootTopic>> getRootTopicListLD(String subject){

        return topicRepository.getRootTopicLD(subject);
    }
}

使用recyclerview的用户界面活动

public class LectureRoomActivity extends AppCompatActivity {
    ...
    private LectureViewModel lectureRoomVM;
    ...
    private RecyclerView mainRecyclerView;

    private RootTopicAdapter rootTopicAdapter;

    ...

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

        Intent intent = getIntent();
        subject = intent.getStringExtra(AppConstant.Constants.SUBJECT);

        mainRecyclerView = findViewById(R.id.recyclerView);

        downloadVM = new ViewModelProvider(this).get(DownloadLectureViewModel.class);
        lectureRoomVM = new ViewModelProvider(this).get(LectureViewModel.class);
        lectureRoomVM.getRootTopicListLD(subject).observe(
                this,
                new Observer<ArrayList<RootTopic>>() {
            @Override
            public void onChanged(ArrayList<RootTopic> rootTopics) {
                if (rootTopics != null){
                    currentTopic = lectureRoomVM.getCursorTopic(subject, rootTopics);
                    setUpRec(rootTopics, currentTopic);
                    // Exactly here, after setting up the data get your index for example
                    if(lectureRoomVM.mustRestore){
                        // Check the item count in the adaptor to avoid crashes
                        if(mainRecyclerView.getAdapter().getItemCount >= lastRecyclerViewIndex){
                            mainRecyclerView.findViewHolderForAdapterPosition(lastRecyclerViewIndex).itemView.performClick();
                        }
                        // After the restoration set the mustRestore to false
                        lectureRoomVM.mustRestore = false;
                    }
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(E, "onDestroy");
        /* 
         * Here just set the mustRestore to true in order to be able to restore in onCreate method.
         * If the application itself is not destroyed your data will still be live in the
         * memory thanks to the ViewModel's life cycle awarness.
         */
        lectureRoomVM.mustRestore = true;
    }
}

给你。请仔细尝试此逻辑,不要出现错误。我想你会得到你想要的。

相关问题