简体   繁体   中英

How to share the data between Fragments using ViewModel

I have a main fragment and inside the main fragment, I have a ViewPager that consists of Nested Fragment (Detail Fragment & Summary Fragment). If I click the button in the main fragment, the data will be set in both the main fragment and Detail fragments in the ViewPager. The problem is how do I get the data from the main fragments that can be used in Detail fragments?

I tried using ViewModel in the main fragment. Suppose that the data should be passing in Detail Fragment.

//Main 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();
                }
            }
        }
    }
};

//Details 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;
}

//View Model

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;
}

在此处输入图像描述

You're passing in the wrong Lifecycle Owner when you're observing your ViewModel's data. In order for both fragments to share the data through the ViewModel, the Lifecycle Owner should be the Activity.

Both Fragments should contain something like the following:

// 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
    }
});

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