想要使用 SharePreferences 更新第二个片段中的数据,但第二个片段未更新

want to update data in second fragment with SharePreferences but second Fragment is not updating

我正在制作一个计算器应用程序,想在第二个片段中更新历史记录,但无法找到在第二个片段中更新 ListView 的完美解决方案。我尝试了很多解决方案,但其中 none 个都可以正常工作。 我正在使用 ViewPager 在计算器和历史片段之间滑动。我累了 bundle class 但是如果我在第一个 Fragment(CalculatorFragment) 的 OnCreat 方法中使用 bundle 和 ViewPager 它会在启动应用程序后显示空白屏幕 & 如果我在 Equal Button 中使用 Bundle class 它会使应用程序崩溃。在这里,我将 viewPager 的 id 作为片段的 Container 传递。

我看到许多答案在使用 Framelayout 作为 Fragments 容器时完美运行,但我想保留 ViewPager 的滑动功能,我尝试了很多解决方案,但其中 none 与 ViewPger 一起正常工作,我将 SharedPreferences 添加到我的代码中,但是当我使用计算器时它没有更新(不是实时的)。 SharedPreferences 似乎有效,但当 App 为 运行 时它们不会更新历史记录 当我重新启动应用程序时,它会显示我在历史片段中的最后一次计算。

我通过了 SharedPreferences 并在第二个片段(历史片段)的 onResume/onStart 方法中获取了字符串,但它只显示了我关闭应用程序时上次计算的历史记录

我正在使用自定义 ArrayList 在历史片段中存储和显示我的历史输出。

每当有人在应用程序中单击“=”按钮时,我想将数据(计算以显示历史记录)传递给 HistoryFragment。 “=”按钮调用计算器应用程序中的相等方法。

正在发生的事情的例子 if I do this calculation in my calculator it does not update

and in History it shows that last one from last when I closed application

这是我到目前为止所做的

这是使用SharedPreferences

在CalculatorFragment.java(第一个片段)中保存答案的代码

我也不知道该用 .appy() 还是 .commit()

public View onCreatView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
         View rootView = inflater.inflate(R.layout.fragment_calculator, container, false);
         SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor mEditor = mPreferences.edit();
         /*
                  other code
         */

public void Equals() {
        String calc = etCalc.getText().toString();
        if (calc.split("\+").length == 2) {
            String[] calculation = calc.split("\+");
            String Ans = String.valueOf(Double.parseDouble(calculation[0]) + 
                             Double.parseDouble(calculation[1]));
            etCalc.setText(Ans);
            tvCalc.setText(calc);
            mEditor.putString("key",calc+"="+Ans);
            mEditor.apply();
       }
}

HistoryFragment.java

import android.content.SharedPreferences;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import java.util.ArrayList;


public class HistoryFragment extends Fragment {
    ArrayList<HistoryList> historyLists;
    SharedPreferences mPreferences;
    String History = "";
    View rootView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_history, container, false);
        return rootView;
    }
    public void onResume(){
        super.onResume();
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
        History = mPreferences.getString("key", "");
        if (History.split("=").length == 2) {
            historyLists = new ArrayList<>();
            historyLists.add(new HistoryList(History.split("=")[0], History.split("=")[1]));
        }
        HistoryAdapter adapter = new HistoryAdapter(getActivity(), historyLists);
        ListView listView = rootView.findViewById(R.id.history);
        listView.setAdapter(adapter);
    }

}

MainActivity.java

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;

import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.widget.Button;


public class MainActivity extends AppCompatActivity {
    ViewPager viewPager;
    pageAdapter pageAdapter;
    Button btnEqual;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @SuppressLint({"SetTextI18n", "UseCompatLoadingForDrawables"})
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = findViewById(R.id.viewPager);
        //Get rid of ActionBar
        ActionBar actionBar = getSupportActionBar();
        assert actionBar != null;
        actionBar.hide();
        pageAdapter = new pageAdapter(getSupportFragmentManager(), 2);
        viewPager.setAdapter(pageAdapter);

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

      <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

如果您需要任何其他应用程序代码,请评论。

我找到了解决这个问题的方法。我们可以使用 Shared ViewModel 通过片段传递数据,无需使用 SharedPreferences。我们可以将文本设置为 ViewModel 并在第二个片段中获取它,即使两个片段都处于恢复状态(两个都处于恢复状态,因为这里我们使用的是简单的 ViewPager)。

我在下面发布我的代码以供参考,我是如何更新第二个片段中的数据的。

MainActivity.java 文件中添加此代码。 两个fragment都需要加,如果只加一个fragment就没有ViewPager的slide效果了。

 getSupportFragmentManager().beginTransaction().add(R.id.viewPager, new CalculatorFragment()).add(R.id.viewPager, new HistoryFragment()).commit();

CalculatorFragment.java 文件中将文本设置到 ViewModel。

public void Equals() {
        String calc = etCalc.getText().toString();
        if (calc.split("\+").length == 2) {
            String[] calculation = calc.split("\+");
            String Ans = String.valueOf(Double.parseDouble(calculation[0]) + 
                             Double.parseDouble(calculation[1]));
            etCalc.setText(Ans);
            viewModel.setText(Ans);
       }
//to send data to ViewModel
  public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        viewModel = ViewModelProviders.of(Objects.requireNonNull(getActivity())).get(SharedViewModel.class);
    }
}

创建一个名为 SharedViewModel.java

的 class
package com.shashank.calculator;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<CharSequence> text = new MutableLiveData<>();
    public void setText(CharSequence input) {
        text.setValue(input);
    }
    public LiveData<CharSequence> getText() {
        return text;
    }
}

最后在第二个 HistoryFragment.java

中从 ViewModel 获取数据
public class HistoryFragment extends Fragment {
 ArrayList<HistoryList> historyLists;
    HistoryAdapter adapter;
    SharedViewModel viewModel;
    String History;
    View rootView;
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_history, container, false);
        listView = rootView.findViewById(R.id.history);
        historyLists = new ArrayList<>();
        return rootView;
    }
 public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // getting data from SharedViewModel and setting it to ListView
        viewModel = ViewModelProviders.of(Objects.requireNonNull(getActivity())).get(SharedViewModel.class);
        viewModel.getText().observe(getViewLifecycleOwner(), charSequence -> {
            History = String.valueOf(charSequence);
            adapter = new HistoryAdapter(Objects.requireNonNull(getActivity()), historyLists);
            historyLists.add(0,History);
            listView.setAdapter(adapter);
            }
        });
    }