【问题标题】:Android: Passing Objects Between FragmentsAndroid:在片段之间传递对象
【发布时间】:2013-11-15 09:56:32
【问题描述】:

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

Passing data between fragments: screen overlap How to pass values between Fragments

以及 Android 文档:

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

还有这篇文章:

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

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

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

我有以下文件:

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

还有以下布局:

activity_register.xml
fragment_register_one.xml
fragment_register_two.xml

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

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

RegisterActivity.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

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(扩展 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

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...
}

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

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

谁能帮我解决这个问题?谢谢

编辑 1:

我试图像这样创建一个快捷方式(不幸的是它不起作用):

在我创建的 RegisterActivity 中:

public Registration regData;

在 RegisterOneFragment 中:

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

终于在RegisterTwoFragment中调用了

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

它抛出一个 nullPointerExceptions

编辑 2

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

【问题讨论】:

标签: java android android-fragments


【解决方案1】:

通过实现 Serializable 到您的自定义对象很容易共享对象。我写了一篇关于这个here的教程。

来自片段一:

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

在片段二中:

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

【讨论】:

  • 对于尝试以更少努力做类似事情的人:使用 google gson 将您的 pojo 序列化为 json 并将其与捆绑包一起发送。它更好,因为您不需要为每个对象实现可序列化,并且当您更改对象属性(在后端)时,您不需要更改可序列化实现。
【解决方案2】:

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

所以如果我理解正确,您希望用户访问RegistrationOneFragment,然后完成后,使用此数据,验证它,如果有效,将其传递给RegistrationTwoFragment 并将用户移动到此Fragment .

您是否可以简单地在您的onEmailRegistered 方法中调用validateJson(regData) 来处理您的活动中的验证,如果成功,则向RegistrationTwoFragment 提交一个事务。

那么您只需要在活动或 Fragment 中使用 getter 和 setter 即可在活动中使用 getRegistrationOneData() 或在 Fragment 中使用 setData(Registration args),如上例所示。

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

【讨论】:

  • 是的,这正是我想要用我的代码做的事情。参考您的解决方案,这是否意味着我不必使用适配器?与此同时,我会尽量听从你的建议。谢谢...
  • 如果你想保留寻呼机和适配器,那么你应该保留它,但我认为你也可以使用 supportFragmentManager() 和事务轻松处理它。
  • 我想你是对的,只是我试图用尽可能少的努力来完成这件事......
【解决方案3】:

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

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

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

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

然后在 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();
    ...

【讨论】:

  • 很高兴为您提供帮助。如果您对 get() 方法解决方案感到满意,请接受答案。
【解决方案4】:

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

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

Android DataCache

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

【讨论】:

  • 这具有单例模式的行为,这是一种非常反模式,单元测试很痛苦。
  • 对于试图以更少的努力做类似事情的人:使用 google gson 将您的 pojo 序列化为 json 并将其与捆绑包 (setArguments) 一起发送。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 2013-06-21
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
相关资源
最近更新 更多