java - 如何使用 ViewModel 在 Fragment 之间共享数据

标签 java android viewmodel

我有一个主要 fragment ,在主要 fragment 内部,我有一个由嵌套 fragment (详细 fragment 和摘要 fragment )组成的 ViewPager。如果我单击主 fragment 中的按钮,数据将同时设置在 ViewPager 的主 fragment 和详细 fragment 中。问题是如何从主要 fragment 中获取可在详细 fragment 中使用的数据?

我尝试在主要 fragment 中使用 ViewModel。假设数据应该传入 Detail Fragment。

//主要 fragment

private void initializeViewPager()
{
    vpExpenses.setOffscreenPageLimit(2);
    setupViewPager(vpExpenses);
}

private void setupViewPager(final ViewPager viewPager)
{
    adapter = new ViewPagerWithTitleAdapter(getFragmentManager());
    adapter.addFragment(new ExpensesDetailsListFragment(), "Detail");
    adapter.addFragment(new ExpensesSummaryListFragment(), "Summary");
    viewPager.setAdapter(adapter);

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
    {
        @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
        @Override public void onPageScrollStateChanged(int state) { }
        @Override public void onPageSelected(int position) {
            if(position == 0)
            {
                tvDetailExpenses.setSelected(true);
                tvSummaryExpenses.setSelected(false);
            }
            else if(position == 1)
            {
                tvDetailExpenses.setSelected(false);
                tvSummaryExpenses.setSelected(true);
            }
        }
    });

    tvDetailExpenses.setSelected(true);
    viewPager.setCurrentItem(0);

    tvDetailExpenses.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v)
        {
            viewPager.setCurrentItem(0,false);
        }
    });

    tvSummaryExpenses.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            viewPager.setCurrentItem(1,false);
        }
    });

}

//Expenses Details List
private void setupExpensesDetailsList(String expenseCategoryId)
{
    expensesViewModel = ViewModelProviders.of(this.getActivity()).get(ExpensesViewModel.class);
    expensesViewModel.setToken(token);
    expensesViewModel.setUserId(userId);
    expensesViewModel.setDeviceId("ABCDE1234567890");
    expensesViewModel.setCarId("24");
    expensesViewModel.setExpensesId(expenseCategoryId);

    getExpensesDetailsList();
}

public void getExpensesDetailsList()
{
    expensesViewModel.getExpensesDetailsList().observe(this, expensesdetailslistObserver);
}

public Observer<ExpensesDetailsListResult> expensesdetailslistObserver = new Observer<ExpensesDetailsListResult>() {
    @Override
    public void onChanged(@Nullable ExpensesDetailsListResult result)
    {
        if(result.getStatus())
        {
            summary = result.getData().getSummary();

            tvTotalExpenses.setText("RM"+summary.getYearly());
            tvExpensesPerDay.setText("/ "+summary.getDaily_avg()+" per day");
        }
        else
        {
            if(!result.getStatus())
            {
                if(result.getCode() == 300)
                {
                    new MaterialDialog.Builder(getActivity())
                            .title("Failed")
                            .content(result.getMsg())
                            .positiveText("OK")
                            .show();
                }
                else if(result.getCode() == 302)
                {
                    new MaterialDialog.Builder(getActivity())
                            .title("Failed")
                            .content(result.getMsg())
                            .positiveText("OK")
                            .show();
                }
            }

            if(result.getRedirectLogin() != null)
            {
                if (result.getRedirectLogin())
                {
                    func.showErrorExpired();
                }
            }
        }
    }
};

//详情 fragment

private ExpensesDetailsListResult expensesDetails;
private List<ExpensesTypes> listExpensesType;

private Unbinder unbinder;
private ExpensesViewModel expensesViewModel;

private Function func;

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View view = inflater.inflate(R.layout.fragment_expenses_list_details, container, false);
    unbinder = ButterKnife.bind(this, view);
    func = new Function(getActivity());

    expensesViewModel = ViewModelProviders.of(this.getActivity()).get(ExpensesViewModel.class);

    expensesViewModel.getExpensesDetailsList().observe(this, item -> {
        //expensesDetails = expensesViewModel.setExpensesDetailsList(item);
    });

    return view;
}

//查看模型

public ExpensesViewModel(@NonNull Application application)
{
    super(application);
}

public void setToken(String token)
{
    this.token = token;
}

public void setUserId(String userId)
{
    this.userId = userId;
}

public void setDeviceId(String deviceId)
{
    this.deviceId = deviceId;
}

public void setCarId(String carId)
{
    this.carId = carId;
}

public void setExpensesId(String expensesId)
{
    this.expensesId = expensesId;
}

//THIS IS THE MAIN FUNCTION THAT UI CONTROLLER CAN OBSERVE FOR CHANGES

//Expenses Category
public MutableLiveData<ExpensesCategoryResult> getExpensesCategory()
{
    expensescategoryObservable = ExpensesRepository.getInstance().getExpensesCategory(token, userId, deviceId);
    return expensescategoryObservable;
}

//Expenses Details List
public MutableLiveData<ExpensesDetailsListResult> getExpensesDetailsList()
{
    expensesdetailslistObservable = ExpensesRepository.getInstance().getExpensesDetailsList(token, userId, deviceId, carId, expensesId, "1");
    return expensesdetailslistObservable;
}

enter image description here

最佳答案

当您观察 ViewModel 的数据时,您传递了错误的生命周期所有者。为了让两个 fragment 通过 ViewModel 共享数据,Lifecycle Owner 应该是 Activity。

两个 fragment 都应该包含如下内容:

// Get the View Model with the Activity as the owner
expensesViewModel = ViewModelProviders.of(getActivity()).get(ExpensesViewModel.class);

// Observe the LiveData by passing in the Activity as the owner, & the observer
expensesViewModel.getExpensesDetailsList().observe(getActivity(),  new Observer<ExpensesDetailsListResult>(){
    @Override
    public void onChanged(ExpensesDetailsListResult result) {
        // Do something with the data according to which Fragment this is in
    }
});

关于java - 如何使用 ViewModel 在 Fragment 之间共享数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58021710/

相关文章:

android - 如何创建 ViewModel 并使用 dagger 2 向其注入(inject)存储库?

java - 在 JDBC 中同时运行 4 个 mysql 查询

java - 为什么 session.persist() 在我的程序中不起作用?

android - 如何将uri转换为inputStream数据并将流数据上传到服务器?

android - 机器人最佳实践。 clickOnView 与 clickOnButton

android - HTTP POST 请求到 PHP 服务器 Android Studio

wpf - 如何在 ViewModel 中呈现( View )模型的集合

java - Spring MVC Controller : what is the difference between "return forward", "return redirect"和 "return jsp file"

java - 无法启动组件 [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]

wpf - ViewModel -> 模型交互