如何在viewpager中的片段之间传递数据?

How to pass data between fragment in viewpager?

有tabLayout和ViewPager。 所以我想将数据从 fragment1 传递到 fragment2。

注意:fragment1 与 fragment2 在于 VIewPager。所以我无法按照正常方式传递数据。

FragmentTransaction fragmentTx=this.FragmentManager.BeginTransaction();
            TracksByGenres fragTrack=new TracksByGenres();
            fragTrack.AddData(items[e.Position]);
            //get our item from listview

            fragmentTx.Replace(Resource.Id.fragmentContainer,fragTrack);    
            fragmentTx.AddToBackStack(null);
            fragmentTx.Commit();

使用sharedPreferences

SharedPreferences sharedpreferences;
public static final String MyPREFERENCES = "MyPrefs" ;
sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

保存价值

SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("TAG_NAME", "value");
editor.commit();

从首选项中检索数据: 在第二个片段中

public static final String MyPREFERENCES = "MyPrefs" ;
SharedPreferences prefs = getSharedPreferences(MyPREFERENCES , MODE_PRIVATE); 
String restoredText = prefs.getString("TAG_NAME", null);

你可以使用一个接口。

public interface DataBoy{
    public void bigDog(Data data);
}

内部片段 1:

DataBoy dataBoy = (DataBoy)getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment2);

dataBoy.bigDog(data);

内部片段 2:

fragment2 implements DataBoy {
...

@Override
public void bigDog(Data data);
doSomethingWith(data);
}

取决于数据的性质。

理想情况下,数据保存在 ActivityViewPager Adapter 中 - 因此当构建每个片段时,它会从 Activity 等中获取数据。请参阅此

我认为最好的解决方案是,如果您可以将数据存储在数据库中,每个 Fragment 通过 CotnentProvider 将数据存储在数据库中,那么您可以使用 Loaders 特别是 CursorLoader 检索数据 - 这种方法将始终为您提供最新数据,因为 Laoder 会在数据更改时收到通知。

在此处查看官方文档以获得 example

我会推荐使用上面建议的首选项来存储除基元等之外的复杂数据以进行设置。

试试下面的代码在片段之间传递数据

Bundle bundle = new Bundle();
FragmentTransaction fragmentTx=this.FragmentManager.BeginTransaction();
TracksByGenres fragTrack=new TracksByGenres();
bundle.putString(key, value); i.e bundle.putString("myKey",items[e.Position]);
fragTrack.setArguments(bundle);
                //get our item from listview
fragmentTx.Replace(Resource.Id.fragmentContainer,fragTrack);    
fragmentTx.AddToBackStack(null);
fragmentTx.Commit();

通过

从调用的片段 onCreate() 中检索数据
Bundle bundle = this.getArguments();
String value= bundle.putString(key, defaultValue); i.e bundle.putString(myKey, "");

最好的方法是使用 SharedPreferences

为此,我们需要像这样定义和初始化 SharedPreferences

SharedPreferences preferences;
public static final String MY_SHARED_PREFERENCES = "MySharedPrefs" ;
preferences = getSharedPreferences(MY_SHARED_PREFERENCES, Context.MODE_PRIVATE);

要节省价值,请使用以下代码。

SharedPreferences.Editor editor = preferences.edit();
editor.putString("YOUR_TAG_NAME", "value");
editor.commit();

要从第二个片段中的 SharedPreferences 检索数据,请使用以下代码

public static final String MY_SHARED_PREFERENCES = "MySharedPrefs" ;
SharedPreferences myPreferences = getSharedPreferences(MY_SHARED_PREFERENCES , MODE_PRIVATE); 
String restoredText = myPreferences.getString("YOUR_TAG_NAME", null);

您也可以使用以下方式在片段之间传递数据,但这种方法有点乏味,如果您有大量数据需要传输到 viewpager 中的另一个片段,这将很有帮助。

将数据从 1st Fragment()(假定为 FirstFragment)传递到 Viewpager 中的 2nd Fragment(假定为 SecondFragment) , 按照以下步骤操作。

第 1 步: 使用如下方法签名创建接口。

public interface ShareIt {
    public void passIt(String data);
}

步骤 2:SecondFragment 需要实现 ShareIt 接口并且应该覆盖 passIt 方法,并且您需要将数据存储在从 FirstFragment 传递的局部变量中。除此之外,我正在传递 Viewpager 实例和 Fragment 索引。需要 Viewpager 的实例作为 findFragmentByTag 方法的参数。所以你的 SecondFragment 看起来像这样。

public class SecondFragment extends Fragment implements ShareIt {

private NonSwipeableViewPager pager;
private int index;
private String string;

public static SecondFragment newInstance(int index, NonSwipeableViewPager viewPager) {
    SecondFragment f = new SecondFragment();
    Bundle args = new Bundle();
    args.putSerializable("VP", viewPager);
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_second, container, false);

    Bundle bundle = getArguments();
    pager = (NonSwipeableViewPager) bundle.getSerializable("VP");
    index = bundle.getInt("index");



    return rootView;
}

@Override
public void passIt(String data) {
    string = data; // Storing the data which is been passed from FirstFargment in a local variable
    Toast.makeText(getActivity(), "" + data, Toast.LENGTH_SHORT).show();
 }
}

第 3 步: 现在我们需要从 FirstFragment 中像这样在 Viewpager 中定位 SecondFragment

Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + pager.getCurrentItem()); 
// pager.getCurrentItem() will give 0, index 0 will have instance of FirstFragment, but we want instance of SecondFragment, so we need to pass 1 instead of pager.getCurrentItem()
Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1); 

有了SecondFragment的instace,我们可以这样调用SecondFragment的passIt方法来传递数据

((SecondFragment)dataBoy).passIt("Hello..!!!!");

所以你的 FirstFragment 看起来像这样。

public class FirstFragment extends Fragment {

private Button btnNext;

private NonSwipeableViewPager pager;
private int index;




public static FirstFragment newInstance(int index, NonSwipeableViewPager viewPager) {
    FirstFragment f = new FirstFragment();
    Bundle args = new Bundle();
    args.putSerializable("VP", viewPager);
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_first, container, false);
    Bundle bundle = getArguments();
    pager = (NonSwipeableViewPager) bundle.getSerializable("VP");
    index = bundle.getInt("index");
    btnNext = findViewById(R.id.btnNext);
    Fragment frag= getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + 1);




    btnNext.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            ((SecondFragment)frag).passIt("Hello..!!!!");           

        }
    });


    return rootView;
  }

}

这是一个老问题,以上所有答案都是 valid.This 是 2019 年,Android 自 Android Architecture Components[= 以来发生了很大变化16=]

如果您使用的是 Android JetPack,那么您可以在 Live Data 上添加一个 Observer承载 Activity class 并监听 Fragment class

中的变化

创建一个 Singleton 存储库来保存实时数据

/**
 * Data Class Live Data
 */
class Repository private constructor() {


    private var currentProgress: MutableLiveData<Float> = MutableLiveData()

    fun getLiveProgress(): MutableLiveData<Float> {
        return currentProgress
    }

    companion object {

        private val mInstance: Repository =
                Repository()

        @Synchronized
        fun getInstance(): Repository {
            return mInstance
        }
    }
}

设置实时数据 Activity 或片段 class class

的任意位置
  viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                headMotionScene.progress = positionOffset
                Repository.getInstance().getLiveProgress().value = positionOffset
            }

            override fun onPageSelected(position: Int) {
            }

        })

从您的片段/服务观察数据变化 class

    Repository.getInstance().getLiveProgress().observe(this, Observer<Float> {
        motionLayout.progress = it
    })