【问题标题】:Passing an Object from an Activity to a Fragment将对象从 Activity 传递到 Fragment
【发布时间】:2012-03-29 19:19:10
【问题描述】:

我有一个Activity,它使用Fragment。我只是想将一个对象从这个Activity 传递给Fragment

我该怎么做? 到目前为止我看到的所有从资源中检索数据的教程。

编辑:

让我们更精确一点:

我的活动左侧有一个ListView。当你点击它时,想法是在右侧加载一个Fragment

当我输入这个Activity 时,通过Intent 给出了一个对象Category。此对象包含一个其他对象列表Questions(其中包含一个字符串列表)。这些Questions 对象显示在ListView 上。 当我单击ListView 中的一项时,我想将String 的列表显示到Fragment(到ListView)中。

为此,我从我的Activity 调用setContentView() 并使用布局。在此布局中定义了 Fragment 以及要调用的正确类。 当我调用这个setContentView() 时,我的FragmentonCreateView() 被调用,但此时getArguments() 返回null。

我怎么能在onCreateView() 的电话之前把它填满? (如果我不够清楚,请告诉我)

谢谢

【问题讨论】:

    标签: android


    【解决方案1】:

    Fragment中创建一个静态方法,然后使用getArguments()获取。

    例子:

    public class CommentsFragment extends Fragment {
      private static final String DESCRIBABLE_KEY = "describable_key";
      private Describable mDescribable;
    
      public static CommentsFragment newInstance(Describable describable) {
        CommentsFragment fragment = new CommentsFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(DESCRIBABLE_KEY, describable);
        fragment.setArguments(bundle);
    
        return fragment;
      }
    
      @Override
      public View onCreateView(LayoutInflater inflater,
          ViewGroup container, Bundle savedInstanceState) {
    
        mDescribable = (Describable) getArguments().getSerializable(
            DESCRIBABLE_KEY);
    
        // The rest of your code
    }
    

    之后您可以从Activity 调用它,执行以下操作:

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    Fragment fragment = CommentsFragment.newInstance(mDescribable);
    ft.replace(R.id.comments_fragment, fragment);
    ft.commit();
    

    【讨论】:

    • 我想传递一些不可序列化的对象是什么?
    • putParcelable 是最佳实践方式
    • 我很想知道为什么不在 newInstance 中简单地设置fragment.mDescribable = describable;?它有效,但是我在这里缺少什么吗?
    • @RahulThakur 你在这里错过了m 前缀的意义。由于 Java 社区强烈鼓励数据封装的概念,应该注意私有字段不需要在外部访问。之所以将其作为参数从单例方法中传递,是因为该字段在该上下文中是必需的,从而降低了您忘记为其赋值的潜在风险。
    • 最佳答案,但你忘了说Object 需要实现Serializable 才能工作(在这种情况下,对象Describable)。
    【解决方案2】:

    在你的活动课上:

    public class BasicActivity extends Activity {
    
    private ComplexObject co;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_page);
    
        co=new ComplexObject();
        getIntent().putExtra("complexObject", co);
    
        FragmentManager fragmentManager = getFragmentManager();
        Fragment1 f1 = new Fragment1();
        fragmentManager.beginTransaction()
                .replace(R.id.frameLayout, f1).commit();
    
    }
    

    注意:你的对象应该实现 Serializable 接口

    然后在你的片段中:

    public class Fragment1 extends Fragment {
    
    ComplexObject co;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Intent i = getActivity().getIntent();
    
        co = (ComplexObject) i.getSerializableExtra("complexObject");
    
        View view = inflater.inflate(R.layout.test_page, container, false);
        TextView textView = (TextView) view.findViewById(R.id.DENEME);
        textView.setText(co.getName());
    
        return view;
    }
    }
    

    【讨论】:

    • 这对我来说很完美!谢谢@Tugce Saritas
    【解决方案3】:

    您应该在片段中创建一个方法,该方法接受您希望传递给它的对象类型。在这种情况下,我将其命名为“setObject”(很有创意吧?:))然后该方法可以对该对象执行您需要的任何操作。

    MyFragment fragment;
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    
            if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
                fragment = new MyFragment();
                getSupportFragmentManager().beginTransaction().add(android.R.id.content, detailsFragment)
                        .commit();
            } else {
               fragment = (MyFragment) getSupportFragmentManager().findFragmentById(
                        android.R.id.content);
            }
    
    
            fragment.setObject(yourObject); //create a method like this in your class "MyFragment"
    }
    

    请注意,我正在使用支持库,并且对 getSupportFragmentManager() 的调用可能只是 getFragmentManager() ,具体取决于您正在使用的内容

    【讨论】:

    • 在可能比您的托管视图更长寿的片段上使用此方法时要小心(retainInstance true)。
    • 这行不通。当您的应用在后台死机,而用户将其带回前台时,setObject 不一定会被调用。
    • @MartinKonecny 在这种情况下将再次调用 onCreate 方法(因为将重新创建活动),因此也会调用 setObject 。如果不是这种情况,请解释您的评论。谢谢。
    • 这在查看寻呼机片段的情况下不起作用。因为对象没有保留在转换中。
    【解决方案4】:

    通过 bundle 传递参数仅限于某些数据类型。但是您可以通过这种方式将任何数据传输到您的片段:

    在你的片段中创建一个像这样的公共方法

    public void passData(Context context, List<LexItem> list, int pos) {
        mContext = context;
        mLexItemList = list;
        mIndex = pos;
    }
    

    在实例化片段后,在您的活动中调用 passData() 并使用您需要的所有数据类型

            WebViewFragment myFragment = new WebViewFragment();
            myFragment.passData(getApplicationContext(), mLexItemList, index);
            FragmentManager fm = getSupportFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            ft.add(R.id.my_fragment_container, myFragment);
            ft.addToBackStack(null);
            ft.commit();
    

    备注:我的片段扩展了“android.support.v4.app.Fragment”,因此我必须使用“getSupportFragmentManager()”。当然,这个原理也适用于扩展“Fragment”的片段类,但是你必须使用“getFragmentManager()”。

    【讨论】:

      【解决方案5】:

      从以下示例中获取参考。

      1.在片段中: 为您希望片段中的对象的类创建一个引用变量。只需为引用变量创建一个 setter 方法并在从活动中替换片段之前调用 setter。

       MyEmployee myEmp;
       public void setEmployee(MyEmployee myEmp)
       {
           this.myEmp = myEmp;
       }
      

      2。活动中:

         //we need to pass object myEmp to fragment myFragment
      
          MyEmployee myEmp = new MyEmployee();
      
          MyFragment myFragment = new MyFragment();
      
          myFragment.setEmployee(myEmp);
      
          FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
          ft.replace(R.id.main_layout, myFragment);
          ft.commit();
      

      【讨论】:

        【解决方案6】:

        要将对象传递给片段,请执行以下操作:

        首先将对象存放在Bundle中,别忘了将实现可序列化的类放在类中。

                    CategoryRowFragment fragment = new CategoryRowFragment();
        
                    // pass arguments to fragment
                    Bundle bundle = new Bundle();
        
                    // event list we want to populate
                    bundle.putSerializable("eventsList", eventsList);
        
                    // the description of the row
                    bundle.putSerializable("categoryRow", categoryRow);
        
                    fragment.setArguments(bundle);
        

        然后在 Fragment 中检索 bundle

               // events that will be populated in this row
                mEventsList = (ArrayList<Event>)getArguments().getSerializable("eventsList");
        
                // description of events to be populated in this row
                mCategoryRow = (CategoryRow)getArguments().getSerializable("categoryRow");

        【讨论】:

          【解决方案7】:

          如果数据应该在整个应用程序生命周期中存在并在多个片段或活动之间共享,则可以考虑使用Model 类,它的序列化开销更少。

          查看design example

          【讨论】:

            【解决方案8】:

            这个对我有用:

            活动中:

            User user;
            public User getUser(){ return this.user;}
            

            在 Fragment 的 onCreateView 方法中:

            User user = ((MainActivity)getActivity()).getUser(); 
            

            MainActivity 替换为您的活动名称。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-02-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-11-12
              相关资源
              最近更新 更多