如何在Fragments
之间传递数据。
我已经创建了InstructionActivity
,InstructionsFragment
,StepsFragment
和SharedViewModel
。我正在尝试将String从InstructionsFragment
传递到StepsFragment
这是我的logCat
中的结果:
D / StepsFragment:THIS com.shawn.nichol.bakingapp.Fragments.SharedViewModel@23e39c0
我还将整个代码放在GitHub上。
SharedViewModel:
public class SharedViewModel extends ViewModel {
private final MutableLiveData<String> stepPosition = new MutableLiveData<>();
public void setStepPosition(String position) {
stepPosition.setValue(position);
}
public MutableLiveData getStepPosition() {
return stepPosition;
}
}
说明片段:
public class InstructionsFragment extends Fragment {
private static final String LOGTAG = "InstructionsFragment";
private RecyclerView mRecyclerView;
private InstructionsAdapter mAdapter;
private String mAllIngredients;
private SharedViewModel model;
// Empty constructor
public InstructionsFragment() {
}
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle onSavedInstanceState) {
View view = inflater.inflate(R.layout.fragment_instructions, container, false);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
mRecyclerView = (RecyclerView) view.findViewById(R.id.ingredients_instructions_rv_fragments);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity().getApplicationContext(),
mRecyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
Log.d(LOGTAG, "Step " + (position + 1) + " " +
InstructionsExtractSteps.stepsShortDescriptionList.get(position));
model.setStepPosition("HELP");
FragmentManager mFragmentManager = getFragmentManager();
StepsFragment mStepsFragment = new StepsFragment();
FragmentTransaction mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction
.replace(R.id.instructions_place_holder, mStepsFragment)
// Puts InstructionsFragment on back stack, when back button is press it will
// reload that fragment instead of going back to the RecipeActivity.
.addToBackStack(null)
.commit();
}
@Override
public void onLongClick(View view, int position) {
}
}));
mAdapter = new InstructionsAdapter();
mRecyclerView.setAdapter(mAdapter);
return view;
}
/**
* onViewCreated: I found this to be the only way to update the TextView in fragment_instructions.xml
*
* @param view
* @param savedInstanceState
*/
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState){
TextView mLoadIngredients = (TextView)getView().findViewById(R.id.ingredients_tv_fragment);
// Set ingredients to screen
for(int i = 0; i < InstructionsExtractIngredients.ingredientList.size(); i++) {
if(i == 0) {
mAllIngredients = "- " + InstructionsExtractIngredients.ingredientList.get(i);
} else {
mAllIngredients = mAllIngredients + "\n - " + InstructionsExtractIngredients.ingredientList.get(i);
}
}
Log.d(LOGTAG, mAllIngredients);
mLoadIngredients.setText(mAllIngredients);
}
}
步骤片段:
public class StepsFragment extends Fragment {
private static final String LOGTAG = "StepsFragment";
// Requires an empty constructor
public StepsFragment() {
}
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_step, container, false);
final SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getStepPosition();
Log.d(LOGTAG, "THIS " + model);
return view;
}
}
答案 0 :(得分:2)
您可以使用接口来允许两个片段及其未弃用之间的通信
但是更好的替代选择是使用架构组件
只需将以下库添加到您的应用gradle文件
implementation 'android.arch.lifecycle:extensions:1.1.1'
implementation 'android.arch.lifecycle:runtime:1.1.1'
,然后创建如下所示的类
import android.arch.lifecycle.ViewModel;
import android.support.annotation.NonNull;
public class TestViewModel extends ViewModel {
private MutableLiveData<String> fragmentAClicked;
public LiveData<String> getFragmentAClicked() {
if (fragmentAClicked == null) {
fragmentAClicked = new MutableLiveData<String>();
}
return fragmentAClicked;
}
public void fragmentAIsClicked(){
fragmentAClicked.setValue("I am clicked")
}
}
在活动类中添加以下代码
public class MyActivity extends AppCompatActivity {
TestViewModel model;
public void onCreate(Bundle savedInstanceState) {
model = ViewModelProviders.of(this).get(TestViewModel.class);
}
}
假设您有两个片段A和B
public class FragmentB extends Fragment {
private TestViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model =ViewModelProviders.of(getActivity()).get(TestViewModel.class);
//communicating with fragment
model.fragmentAIsClicked();
}
}
public class FragmentA extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TestViewModel model = ViewModelProviders.of(getActivity()).get(TestViewModel.class);
model.getFragmentAClicked().observe(this, { msg ->
Log.d("test","message from fragmentA is " + msg)
});
}
}
所以基本上,您的想法是基于mvvm设计模式的viewmodel类,该类可处理活动,片段之间使用事件进行的所有通信
有关更多信息,请检查此here
答案 1 :(得分:0)
我不知道您的目的是什么,但是您可以使用POJO
类在片段之间传递。
public class Test {
public static class FragmentScanIDGInfo {
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
String lastName = "";
String firstName = "";
public static FragmentScanIDGInfo shared;
public static FragmentScanIDGInfo sharedSingleton() {
if (shared == null) {
shared = new FragmentScanIDGInfo();
}
return shared;
}
FragmentScanIDGInfo() {
this.setLastName("");
this.setFirstName("");
}
}
}
您可以设置并达到自己的目的,例如:
Test.FragmentScanIDGInfo scanDataFragment = Test.FragmentScanIDGInfo.sharedSingleton();
scanDataFragment.setFirstName(""); /* set data first name */
scanDataFragment.getFirstName(); /* get data first name */