【问题标题】:How to pass data between fragment in viewpager?如何在 viewpager 中的片段之间传递数据?
【发布时间】:2016-06-07 16:19:51
【问题描述】:

有一个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();

【问题讨论】:

  • 您可以使用基于事件的解决方案,我在 viewpager 中有 2 个片段并成功传递了数据。去搜索 EventBus。如果你愿意,我可以给你工作示例。

标签: android xamarin xamarin.android


【解决方案1】:

使用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);

【讨论】:

  • 不推荐
【解决方案2】:

这是一个老问题,以上所有答案都是有效的。这是 2019 年,Android 自 Android Architecture Components

以来发生了很大变化

如果您使用的是 Android JetPack,则可以在 Host Activity 类中的 Live Data 上添加 Observer 并监听 Fragment 类的变化

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

/**
 * 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 或 Fragment 类的任何地方

  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) {
            }

        })

观察 Fragment/Service 类中的数据变化

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

【讨论】:

  • 如果您是 livedata 新手,请查看 this example 以获得更好的理解
【解决方案3】:

您可以使用接口。

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

【讨论】:

    【解决方案4】:

    最好的方法是使用 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 中的另一个片段,这将很有帮助。

    要将数据从 Viewpager 中的 1st Fragment()(假设为 FirstFragment)传递到 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的实例,我们可以调用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;
      }
    
    }
    

    【讨论】:

      【解决方案5】:

      尝试以下代码在片段之间传递数据

      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, "");
      

      【讨论】:

        【解决方案6】:

        取决于数据的性质。

        理想情况下,数据保存在ActivityViewPager Adapter- 所以当构建每个片段时,它会从活动等获取数据。请参阅question on SO

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

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

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

        【讨论】:

        • @Zain 感谢您的更新!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-25
        • 1970-01-01
        • 1970-01-01
        • 2011-07-08
        • 2019-10-05
        • 2015-08-21
        相关资源
        最近更新 更多