我在 ViewPager Activity 中有 3 个 fragment 。所有 3 个 fragment 都有输入字段。在这里,我试图将前两个 fragment 数据传递给第三个 fragment 。我在这里读了几篇文章,其中大多数建议使用接口(interface)(即通过父 Activity 传递数据) 我也通过了这个链接 http://developer.android.com/training/basics/fragments/communicating.html
接口(interface):当我们通过某些用户事件发送数据时,使用接口(interface)是一种很好的方法。在这里,我试图在没有任何用户事件的情况下发送数据。因此我想到了 onPause() 因为 onPause() 总是被调用。但是 ViewPager 的功能不同。加载一个 fragment 时,也会加载相邻的 fragment 。我会成功地在第一个 fragment 和第三个 fragment 之间传递数据。但是第二个 fragment 的 onPause() 不会被调用,除非我导航到一些不相邻的 fragment (在我的例子中不存在)
Setter/Getters:我在一些帖子中看到有人说不要使用setter/getters(我还没有明白原因)Are getters and setters poor design? Contradictory advice seen
bundle :我还没有考虑过这个。由于我在这里再次感到困惑,我将如何使用 bundle 传递数据。(我应该在哪个方法中发送数据?以及如何发送数据?)
抱歉,如果我的问题听起来很愚蠢。我正在尝试理解 fragment ,我想知道在 viewpager 中的 fragment 之间传递数据的最佳方式。 提前谢谢你。
TabPAgerAdapter -->
package com.jbandroid.model;
import com.jbandroid.fragment.LocationInfoFragment;
import com.jbandroid.fragment.PersonalInfoFragment;
import com.jbandroid.fragment.PostInfoFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm){
super(fm);
}
@Override
public Fragment getItem(int index) {
switch(index) {
case 0 : //PostInfoFragment
return new PostInfoFragment();
case 1 : //LocationInfoFragment
return new LocationInfoFragment();
case 2 : //PersonalInfoFragment
return new PersonalInfoFragment();
}
return null;
}
@Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
ViewPagerActivity -->
package com.jbandroid;
public class SubmitPostActivity extends FragmentActivity implements ActionBar.TabListener,PostInfoFragment.setPostInfo,LocationInfoFragment.setLocationInfo{
private ViewPager viewpager;
private ActionBar actionBar;
private TabsPagerAdapter mAdapter;
FragmentManager manager;
PersonalInfoFragment frag;
List<String> location;
/*private MenuItem myActionMenuItem;
private Button myActionButton;*/
//Tab titles
private String[] tabs = {"Post Info" , "Location Info" , "Personal Info" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.action_submit_post);
viewpager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
manager = getSupportFragmentManager();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
//viewpager.setOffscreenPageLimit(2);
viewpager.setAdapter(mAdapter);
//actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tab : tabs){
actionBar.addTab(actionBar.newTab().setText(tab).setTabListener(this));
}
if(savedInstanceState != null){
actionBar.setSelectedNavigationItem( savedInstanceState.getInt("tab",0));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewpager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void pass_location_details(List<String> location) {
frag = (PersonalInfoFragment) manager.findFragmentByTag("android:switcher:" + viewpager.getId() + ":" + 2);
frag.get_post_location_details(location);
Log.d("submitarea", location.get(0));
}
@Override
public void pass_post_details(List<String> post_details,ArrayList<CustomGallery> selected) {
frag = (PersonalInfoFragment) manager.findFragmentByTag("android:switcher:" + viewpager.getId() + ":" + 2);
frag.get_post_details(post_details,selected);
Log.d("submitpostinfo","hello"+ post_details.get(5));
}
}
第一个 fragment (这里我尝试使用 onPause() 中的接口(interface)传递数据-->
package com.jbandroid.fragment;
public class PostInfoFragment extends Fragment {
private MenuItem myActionMenuItem;
private Button myActionButton;
private ActionBar actionBar;
private String post_title, post_desc,post_status;
private EditText submit_post_title, submit_post_desc;
private Resources res;
setPostInfo info;
List<String> post_details;
//RelativeLayout rel_submit_post_start_date,rel_submit_post_end_date;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_post_info,
container, false);
/*if(!imageLoader.isInited()){*/
initImageLoader();
/*}*/
//handler = new Handler();
submit_post_title = (EditText) rootView
.findViewById(R.id.submit_post_title);
submit_post_desc = (EditText) rootView
.findViewById(R.id.submit_post_description);
actionBar = getActivity().getActionBar();
setHasOptionsMenu(true);
post_details = new ArrayList<String>();
res = getResources();
setListeners();
Log.d("postinfo_oncreate view", "postinfo_oncreate view");
return rootView;
}
//interface to pass data to activity and then to PersonalInfoFragment
public interface setPostInfo {
//public void pass_post_details(List<String> post_details);
public void pass_post_details(List<String> post_details,ArrayList<CustomGallery> selected);
}
//making sure if the parent activity has implemented interface
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
info = (setPostInfo) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ "must implemet setPostInfo");
}
Log.d("postinfo_onattach", "postinfo_onattach");
}
//passing form inputs to personalinfofragments
@Override
public void onPause() {
super.onPause();
// setFormInputs();
passFormInputs(); ---> passing in onPause() This executes successfully
Log.d("postinfo_onPAuse", "postinfo_onPause");
}
//method to pass data to personalinfofragment
private void passFormInputs() {
try {
post_title = submit_post_title.getText().toString();
post_desc = submit_post_desc.getText().toString();
post_status = "1";
if(post_title != null && post_title.length() > 0
&& post_desc != null && post_desc.length() > 0
&& post_status != null && post_status.length() > 0
){
post_details.add(post_title);
post_details.add(post_desc);
post_details.add(post_status);
info.pass_post_details(post_details,dataT); -->here I am passing values via
}else{ activity to 3rd fragment
Log.d("post_info", "values are null");
}
} catch (Exception e) {
e.printStackTrace();
}
}
//setting next button on actionbar
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Inflate the menu items for use in the action bar
inflater.inflate(R.menu.mymenu, menu);
// Here we get the action view we defined
myActionMenuItem = menu.findItem(R.id.my_action);
View actionView = myActionMenuItem.getActionView();
// We then get the button view that is part of the action view
if (actionView != null) {
myActionButton = (Button) actionView.findViewById(R.id.action_btn);
myActionButton.setText(R.string.txt_next);
if (myActionButton != null) {
// We set a listener that will be called when the return/enter
// key is pressed
myActionButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
actionBar.setSelectedNavigationItem(1);
}
});
}
}
}
}
第二个 fragment -->
package com.jbandroid.fragment;
public class LocationInfoFragment extends Fragment implements OnClickListener {
private MenuItem myActionMenuItem;
private Button myActionButton;
private ActionBar actionBar;
Dialog dialog;
private EditText submit_post_exact_location;
private TextView selected_country, selected_city,
submit_post_exact_time;
String country, city, exact_location, exact_time;
setLocationInfo info;
List<String> location;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_location_info,
container, false);
actionBar = getActivity().getActionBar();
setHasOptionsMenu(true);
submit_post_exact_location = (EditText) rootView
.findViewById(R.id.submit_post_exact_location);
submit_post_exact_time = (TextView) rootView
.findViewById(R.id.submit_post_exact_time);
selected_country = (TextView) rootView
.findViewById(R.id.selected_country);
selected_city = (TextView) rootView.findViewById(R.id.selected_city);
location = new ArrayList<String>();
setListeners();
return rootView;
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Inflate the menu items for use in the action bar
inflater.inflate(R.menu.mymenu, menu);
// Here we get the action view we defined
myActionMenuItem = menu.findItem(R.id.my_action);
View actionView = myActionMenuItem.getActionView();
// We then get the button view that is part of the action view
if (actionView != null) {
myActionButton = (Button) actionView.findViewById(R.id.action_btn);
myActionButton.setText(R.string.txt_next);
if (myActionButton != null) {
// We set a listener that will be called when the return/enter
// key is pressed
myActionButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
actionBar.setSelectedNavigationItem(2);
}
});
}
}
}
public interface setLocationInfo {
public void pass_location_details(List<String> location);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
info = (setLocationInfo) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ "must implement setLocationInfo");
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//setLocationDetails();
}
@Override
public void onPause() {
super.onPause();
setLocationDetails(); ----> doesnt executes since onPause isnt called when I navigate to 3rd fragment as it is an adjacent fragment of this fragment
// Log.d("location : onPause", area);
}
private void setLocationDetails() {
try {
exact_location = submit_post_exact_location.getText().toString();
exact_time = submit_post_exact_time.getText().toString();
country = selected_country.getText().toString();
city = selected_city.getText().toString();
if (country != null && country.length() > 0
&& !country.equalsIgnoreCase("select") && city != null
&& city.length() > 0 && !city.equalsIgnoreCase("select")
&& exact_location != null && exact_location.length() > 0
&& exact_time != null && exact_time.length() > 0) {
location.add(country);
location.add(city);
location.add(exact_location);
location.add(exact_time);
info.pass_location_details(location);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
在我的第三个 fragment 中,我试图获得这个值
public class PersonalInfoFragment extends Fragment {
List<String> post_details;
List<String> location;
Button submit;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_personal_info,
container, false);
submit = (Button)rootView.findViewById(R.id.submitBtn);
submit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//performing operations with the values obtained
setPostItems();
insertintodb();
}
});
return rootView;
}
public void get_post_details(List<String> post_details,
ArrayList<CustomGallery> selected) { -->receiving values from
this.post_details = post_details; 1st fragment
this.selected = selected;
Log.d("personalfrag(postinfo)", "hello" + post_details.get(5));
}
//receiving values from 2nd fragment
public void get_post_location_details(List<String> location) {
this.location = location;
Log.d("personalfrag(locationinfo)", "hello" + location.get(0));
}
}
最佳答案
好的,我在 ViewPager 的两个选项卡之间传递数据(不仅仅是字符串)时遇到了同样的问题。所以这就是我所做的。 我使用接口(interface)在不同组件之间进行通信。
数据以这种方式传递:
Tab 1 -> Activity -> VewPageAdapter -> Tab 2
- 在选项卡 1 中
创建一个接口(interface)。
OnCartsDataListener mOncarOnCartsDataListener;
public interface OnCartsDataListener {
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mOncarOnCartsDataListener = (OnCartsDataListener)activity;
}catch (ClassCastException e){
}
}
// now call mOncarOnCartsDataListener.onCartsDataReceived(data) when you have the data
- Activity 中
实现接口(interface)并覆盖方法
ViewPagerAdapter adapter;
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs);
@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
Log.d(TAG, "data received to Activity... send to view pager");
adapter.onCartsDataReceived(cartsViewModels);
}
3.在ViewPagerAdapter中
同时实现了接口(interface)并重写了方法
@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
Log.d(TAG, "data received to view pager... sending to tab 2");
if(tab2!=null){
tab2.onCartsDataReceived(cartsViewModels);
}else{
Log.d(TAG, "tab2 is null");
}
}
- 最后是选项卡 2
也实现了接口(interface)并覆盖了方法
@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
Log.d(TAG, "Finally ! received data to tab 2");
if(cartsViewModels!=null){
for(CartsViewModel cart : cartsViewModels){
Log.d(TAG,"got it :"+cart.getCartName());
}
}
}
关于Android:在 viewpager fragment 之间传递数据的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26358043/