Java Android:在片段之间传递对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19998239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:10:26  来源:igfitidea点击:

Android: Passing Objects Between Fragments

javaandroidandroid-fragments

提问by Jeremy

Before i start, i have look through question such as:

在我开始之前,我已经浏览了以下问题:

Passing data between fragments: screen overlapHow to pass values between Fragments

在片段之间传递数据:屏幕重叠如何在片段之间传递值

as well as Android docs:

以及 Android 文档:

http://developer.android.com/training/basics/fragments/communicating.html

http://developer.android.com/training/basics/fragments/communicating.html

as well as this article:

以及这篇文章:

http://manishkpr.webheavens.com/android-passing-data-between-fragments/

http://manishkpr.webheavens.com/android-passing-data-between-fragments/

Though all the cases mentioned above similar to what i have, it is not entirely identical. I followed a good tutorial here (Some portion of my code is based on this article):

虽然上面提到的所有案例都与我所拥有的相似,但并不完全相同。我在这里遵循了一个很好的教程(我的代码的某些部分基于本文):

http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/

http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/

I have the following files:

我有以下文件:

RegisterActivity.java
NonSwipeableViewPager.java
ScreenSliderAdapter.java
RegisterOneFragment.java
RegisterTwoFragment.java

RegisterActivity.java
NonSwipeableViewPager.java
ScreenSliderAdapter.java
RegisterOneFragment.java
RegisterTwoFragment.java

And the following layouts:

以及以下布局:

activity_register.xml
fragment_register_one.xml
fragment_register_two.xml

activity_register.xml
fragment_register_one.xml
fragment_register_two.xml

What i am trying to achieve is passing an Serializable object from RegisterFragmentOne to RegisterFragmentTwo.

我想要实现的是将 Serializable 对象从 RegisterFragmentOne 传递到 RegisterFragmentTwo。

So far this is what i have done (some codes are omitted):

到目前为止,这是我所做的(省略了一些代码):

RegisterActivity.java

注册活动.java

public class RegisterActivity extends FragmentActivity
             implements RegisterOneFragment.OnEmailRegisteredListener{

    public static NonSwipeableViewPager viewPager;
    private ScreenSliderAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);

        // Initilization
        mAdapter = new ScreenSliderAdapter(getSupportFragmentManager());
        viewPager = (NonSwipeableViewPager) findViewById(R.id.pager);
        viewPager.setAdapter(mAdapter);
    }

    public void onEmailRegistered(int position, Registration regData){
        Bundle args = new Bundle();
        args.putSerializable("regData", regData);
        viewPager.setCurrentItem(position, true);
    }
}

ScreenSliderAdapter.java

屏幕滑块适配器.java

public class ScreenSliderAdapter extends FragmentPagerAdapter{

    public ScreenSliderAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:
            return new RegisterOneFragment();
        case 1:
            return new RegisterTwoFragment();
        case 2:
            return new RegisterThreeFragment();
        }

        return null;
    }

    @Override
    public int getCount() {
        return 3;
    }
}

NonSwipeableViewPager.java(extending ViewPager class, and overrides the following)

NonSwipeableViewPager.java(扩展 ViewPager 类,并覆盖以下内容)

@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
    // Never allow swiping to switch between pages
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Never allow swiping to switch between pages
    return false;
}

RegisterOneFragment.java

注册一个片段.java

public class RegisterOneFragment extends Fragment {
    OnEmailRegisteredListener mCallBack;
    public interface OnEmailRegisteredListener {
        /** Called by RegisterOneFragment when an email is registered */
        public void onEmailRegistered(int position, Registration regData);
    }

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 {
        mCallBack = (OnEmailRegisteredListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnEmailRegisteredListener");
    }
}

... And some to execute some HTTP request via separate thread...
}

What i am trying to accomplish is that when ever a user pressed a button on RegisterOneFragment, a data will be sent to a server (and returns some validation over JSON). If the returned data is valid, the the application should go to the next fragment which is RegistrationTwoFragment.

我想要完成的是,当用户按下 RegisterOneFragment 上的按钮时,数据将发送到服务器(并通过 JSON 返回一些验证)。如果返回的数据有效,则应用程序应转到下一个片段,即 RegistrationTwoFragment。

I am having some confusion as how to pass objects between fragments, since my Fragments is created using an Adapter. And that Adapter is then attached to my Activity.

我对如何在片段之间传递对象有些困惑,因为我的片段是使用适配器创建的。然后将该适配器附加到我的活动。

Can anyone help me with this? Thx

谁能帮我这个?谢谢

Edit 1:

编辑1:

I tried to make a shortcut (unfortunately does not work) like so:

我试图制作一个快捷方式(不幸的是不起作用),如下所示:

In RegisterActivity i created:

在我创建的 RegisterActivity 中:

public Registration regData;

and in RegisterOneFragment:

在 RegisterOneFragment 中:

/* PLACED ON POST EXECUTE */
((RegisterActivity)getActivity()).regData = regData;

Finally called it in RegisterTwoFragment

最后在 RegisterTwoFragment 中调用它

Registration regData;
regData = ((RegisterActivity) getActivity()).regData;

It throws a nullPointerExceptions

它抛出一个 nullPointerExceptions

Edit 2

编辑 2

Just to be clear, RegisterActivty contains multiple fragments. And the only way user can navigate between fragment is by clicking a button. The Activity has no Tab bar.

需要明确的是,RegisterActivty 包含多个片段。用户可以在片段之间导航的唯一方法是单击按钮。活动没有标签栏。

采纳答案by sturrockad

I would normally have setters or methods similar to this in the containing activity.

我通常会在包含活动中使用与此类似的设置器或方法。

So if I understand correctly, you want the user to access RegistrationOneFragment, then when completed, use this data, validate it, and if valid, pass it along to RegistrationTwoFragmentand move the user to this Fragment.

因此,如果我理解正确,您希望用户访问RegistrationOneFragment,然后在完成后使用此数据,对其进行验证,如果有效,则将其传递给RegistrationTwoFragment并将用户移动到此Fragment

Could you simply call validateJson(regData)in your onEmailRegisteredmethod to handle the validation in your activity, if it succeeds, commit a transaction to RegistrationTwoFragment.

您能否简单地调用validateJson(regData)您的onEmailRegistered方法来处理您的活动中的验证,如果成功,将事务提交到RegistrationTwoFragment.

Then all you need are getters and setters in your activity or Fragment to say getRegistrationOneData()in the activity or setData(Registration args)in the fragment as your examples show above.

然后,您所需要的只是您的活动或片段中的 getter 和 setter,以在活动或片段中说明getRegistrationOneData()setData(Registration args)如上面的示例所示。

I don't know of any way to pass the args directly into the Fragment.

我不知道有什么方法可以将 args 直接传递到 Fragment 中。

回答by Jeremy

I found a solution to my question, which i am sure not the correct way to do that...

我找到了我的问题的解决方案,我确定这不是正确的方法......

So in RegisterActivity.java i add + modified the following lines (thx to @sturrockad):

所以在 RegisterActivity.java 我添加+修改了以下几行(感谢@sturrockad):

public Registration getRegistrationData(){
    return this.regData;
}

public void onEmailRegistered(int position, Registration regData){
    this.regData = regData;
    viewPager.setCurrentItem(position, true);
}

Then in RegisterTwoFragments.java (or in the Fragment to which i want to receive the Object):

然后在 RegisterTwoFragments.java (或在我想接收对象的片段中):

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_register_two, container, false);
    regData = ((RegisterActivity) getActivity()).getRegistrationData();
    ...

回答by Shihab Uddin

It's easy to share objects via implementing Serializable to your custom Object. I wrote a tutorial about this here.

通过对自定义对象实现 Serializable 来共享对象很容易。我在这里写了一个关于这个的教程。

From Fragment One:

从片段一:

android.support.v4.app.FragmentTransaction ft = 
    getActivity().getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
OfficeCategoryFragment frag = new OfficeCategoryFragment();

Bundle bundles = new Bundle();
Division aDivision = divisionList.get(position);

// ensure your object has not null
if (aDivision != null) {
    bundles.putSerializable("aDivision", aDivision);
    Log.e("aDivision", "is valid");
} else {
    Log.e("aDivision", "is null");
}
frag.setArguments(bundles);
ft.replace(android.R.id.content, frag);
ft.addToBackStack(null);
ft.commit();

In Fragment two:

在片段二中:

Bundle bundle = getArguments();
Division division= (Division) bundle.getSerializable("aDivision");
Log.e("division TEST", "" + division.getName());

回答by kimkevin

I used to set object with Pacelable or Serializable to transfer, but whenever I add other variables to object(model), I have to register it all. It's so inconvenient.

我曾经使用 Pacelable 或 Serializable 设置对象进行传输,但是每当我向对象(模型)添加其他变量时,我都必须将其全部注册。太不方便了

It's super easy to transfer object between activities or fragments.

在活动或片段之间传输对象非常容易。

Android DataCache

安卓数据缓存

  1. put your data object to KimchiDataCache instance in your activity or fragment.

    User userItem = new User(1, "KimKevin");  // Sample Model
    
    KimchiDataCache.getInstance().put(userItem);
    
    // add your activity or fragment
    
  2. Get your data object in your activity of fragment that you added.

    public class MainFragment extends Fragment{
         private User userItem;
    
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
    
             userItem = KimchiDataCache.getInstance().get(User.class);
         }
    
  1. 将您的数据对象放入您的活动或片段中的 KimchiDataCache 实例。

    User userItem = new User(1, "KimKevin");  // Sample Model
    
    KimchiDataCache.getInstance().put(userItem);
    
    // add your activity or fragment
    
  2. 在您添加的片段活动中获取您的数据对象。

    public class MainFragment extends Fragment{
         private User userItem;
    
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
    
             userItem = KimchiDataCache.getInstance().get(User.class);
         }