Reputation: 55
I have 2 fragment in activityty a list fragment and details fragment,details fragment showing selected items details from list fragment and there is button to change list item "status" set order as ready.
I want to move selected item to ready seaction when button Order is ready clicked.
I tried it with observing with shared view model but onchange method not calling when I set value in it.
here is a viewModel:
package com.example.ordermanager.fragments;
import android.database.ContentObserver;
import android.os.Handler;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.example.ordermanager.fragments.orderlist.dummy.DummyContent;
import java.util.List;
public class SharedViewModel extends ViewModel {
private MutableLiveData<DummyContent.DummyItem> item = new MutableLiveData<DummyContent.DummyItem>();
public void setItem(DummyContent.DummyItem value){
item.setValue(value);
}
public MutableLiveData<DummyContent.DummyItem> getItem(){
return item;
};
}
ListFragment:
public class OrderItemFragment extends Fragment {
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
private OnListFragmentInteractionListener mListener;
private SharedViewModel vm;
private RecyclerView recyclerView;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public OrderItemFragment() {
}
// TODO: Customize parameter initialization
@SuppressWarnings("unused")
public static OrderItemFragment newInstance(int columnCount) {
OrderItemFragment fragment = new OrderItemFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
vm = ViewModelProviders.of(this).get(SharedViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_order_item_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new MyOrderItemRecyclerViewAdapter(DummyContent.ITEMS, mListener));
}
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Observer<DummyItem> itemObserver = new Observer<DummyItem>() {
@Override
public void onChanged(@Nullable DummyItem selectedItem) {
//this never happening
Log.e("hereeeee","dfgdfg");
recyclerView.getAdapter().notifyDataSetChanged();
}
};
vm.getItem().observe(this, itemObserver);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener) {
mListener = (OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnListFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnListFragmentInteractionListener {
// TODO: Update argument type and name
void onListFragmentInteraction(DummyItem item);
}
}
DetailsFragment:
public class OrderDetailFragment extends Fragment {
private SharedViewModel mViewModel;
private DummyContent.DummyItem selectedItem;
private Button ReadyBtn;
public static OrderDetailFragment newInstance() {
return new OrderDetailFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.order_detail_fragment, container, false);
Bundle bundle = getArguments();
if(bundle != null){
selectedItem = (DummyContent.DummyItem)getArguments().getSerializable("item");
TextView tv = (TextView) view.findViewById(R.id.detailid);
tv.setText(selectedItem.content);
}
ReadyBtn = view.findViewById(R.id.readyBtn);
ReadyBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedItem != null){
selectedItem.isReady = true;
mViewModel.getItem().setValue(selectedItem);
}
}
});
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(SharedViewModel.class);
}
}
Observer is in ListFragment OnViewCreated function
Any Ideas?
Upvotes: 0
Views: 7186
Reputation: 326
You should change the data in your adapter before calling notifyDataSetChanged()
method. Now you are getting new value in itemObserver
but you're not changing the adapter.
UPD. I've solved the problem! The key in your initialization code of SharedViewModel
. You should attach activity to the ViewModelProviders
class in both cases, but you use this and in reality you have two different instances instead of one which should be attached to the parent activity. So, change the code of initialization to
mViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
and it'll work!
Upvotes: 2
Reputation: 974
When you declare local variables in functions, they get destroyed when the function call ends. Therefore you need to store your itemObserver
in a field.
On a side note...
You don't need a default empty constructor in fragments unless you create a custom one, which isn't recommended.
Regarding recyclerview
I would recommend reading this in detail (especially the ListAdapter
part).
Upvotes: 0