在Android中将数据从活动发送到片段

use*_*569 284 android android-fragments

我有两节课.首先是活动,第二是我有一些片段EditText.在活动中我有一个带有async-task的子类,在方法中doInBackground我得到一些结果,我保存到变量.如何将此变量从子类"my activity"发送到此片段?

ρяσ*_*я K 607

从活动中您可以按意图发送数据:

Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
Run Code Online (Sandbox Code Playgroud)

并在Fragment onCreateView方法中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    String strtext = getArguments().getString("edttext");    
    return inflater.inflate(R.layout.fragment, container, false);
}
Run Code Online (Sandbox Code Playgroud)

  • 嗯,当调用`getArguments()时,我得到一个NullPointerException .getString(key)` (55认同)
  • 你可以将一个对象传递给片段吗? (12认同)
  • NullPointerException"String strtext setArguments().getString("edttext");" (9认同)
  • 在读取片段中的bundle内容时,总是首先使用getArguments方法将bundle接收到Bundle对象中,并将其检查为null.否则,getString方法将应用于null,因此在没有传递bundle时应用NPE.这将避免在未传递bundle时出现空指针异常. (3认同)
  • @Aznix.不建议为片段创建构造函数. (3认同)
  • @DileepaNipunSalinda:是的,但要确保类正在实现可序列化或可打包 (2认同)

Ric*_*das 102

您还可以从片段访问活动数据:

活动:

public class MyActivity extends Activity {

    private String myString = "hello";

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

    public String getMyData() {
        return myString;
    }
}
Run Code Online (Sandbox Code Playgroud)

分段:

public class MyFragment extends Fragment {

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

        MyActivity activity = (MyActivity) getActivity();
        String myDataFromActivity = activity.getMyData();
        return view;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案集成了您的活动和Fragment之间的紧密耦合,更好地使用`Bundle`类来传递信息.或者,您可以从接口继承并实现`getMyData()`方法,并使用`Fragment`检查getActivity是否在`onAttach()`中返回`instanceof`接口. (73认同)
  • 这应该*不是*接受的答案.紧耦合很容易避免.这通常是一个坏主意,并且使得片段无用,如果你只是将它用于绑定到一个活动,那么也可能没有片段.该片段不能在其他活动中重复使用. (7认同)
  • 当前接受的答案返回空指针异常。这应该是公认的答案 (2认同)

Jor*_*sys 42

我在这里找到了很多答案@ stackoverflow.com但是这肯定是正确的答案:

"将数据从活动发送到android中的片段".

活动:

        Bundle bundle = new Bundle();
        String myMessage = "Stackoverflow is cool!";
        bundle.putString("message", myMessage );
        FragmentClass fragInfo = new FragmentClass();
        fragInfo.setArguments(bundle);
        transaction.replace(R.id.fragment_single, fragInfo);
        transaction.commit();
Run Code Online (Sandbox Code Playgroud)

分段:

读取片段中的值

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = this.getArguments();
        String myValue = bundle.getString("message");
        ...
        ...
        ...
        }
Run Code Online (Sandbox Code Playgroud)

要不就

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        String myValue = this.getArguments().getString("message");
        ...
        ...
        ...
        }
Run Code Online (Sandbox Code Playgroud)

  • 插入字符串或整数的对象怎么样? (3认同)
  • @Jorgesys 这个解决方案怎么样?https://developer.android.com/training/basics/fragments/communicating.html (3认同)

Noo*_*rul 16

这个答案可能为时已晚.但它对未来的读者会很有用.

我有一些标准.我编码从意图中选择文件.和选定的文件传递给特定的片段以进行进一步的处理.我有许多具有文件选择功能的片段.在那个时候,每次检查条件并获得片段并传递该值是非常恶心的.所以,我决定使用界面传递值.

第1步:在主要活动上创建界面.

   public interface SelectedBundle {
    void onBundleSelect(Bundle bundle);
   }
Run Code Online (Sandbox Code Playgroud)

第2步:在相同活动中创建方法

   SelectedBundle selectedBundle;
Run Code Online (Sandbox Code Playgroud)

第3步:在Same Activity上创建SelectedBundle引用

   public void setOnBundleSelected(SelectedBundle selectedBundle) {
       this.selectedBundle = selectedBundle;
   }
Run Code Online (Sandbox Code Playgroud)

第4步:需要初始化SelectedBundle引用,这些引用都是片段需要的文件选择器功能.您可以将此代码放在片段onCreateView(..)方法上

    ((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() {
          @Override
         public void onBundleSelect(Bundle bundle) {
            updateList(bundle);
        }
     });
Run Code Online (Sandbox Code Playgroud)

步骤5:来自MainActivity的onActivityResult,使用接口将值传递给片段.

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent  data) {
       selectedBundle.onBundleSelect(bundle);
  }
Run Code Online (Sandbox Code Playgroud)

就这样.在FragmentClass上实现您需要的每个片段.你很棒.你做完了 哇...


diy*_*da_ 13

使用Fragments(F)的基本思想是在Android应用程序中创建可重用的自我维持UI组件.这些碎片包含在活动中,并且存在从A - > F和FA创建通信路径的通用(最佳)方式,通过活动在FF之间进行通信是必须的,因为这样只有碎片变得分离并且自我维持.

因此,从A - > F传递数据将与ρяσѕρєяK所解释的相同.除了答案之外,在Activity中创建Fragments之后,我们还可以将数据传递给片段中的片段调用方法.

例如:

    ArticleFragment articleFrag = (ArticleFragment)
                    getSupportFragmentManager().findFragmentById(R.id.article_fragment);
    articleFrag.updateArticleView(position);
Run Code Online (Sandbox Code Playgroud)


Pre*_*ker 12

最方便的方法是调用片段实例并在那时发送数据. 默认情况下每个片段都有实例方法

例如:如果您的片段名称是MyFragment

所以你将从这样的活动中调用你的片段:

getSupportFragmentManager().beginTransaction().add(R.id.container, MyFragment.newInstance("data1","data2"),"MyFragment").commit();
Run Code Online (Sandbox Code Playgroud)

*R.id.container是我的FrameLayout的id

所以在MyFragment.newInstance("data1","data2")中,您可以将数据发送到片段,在片段中,您可以在MyFragment newInstance中获取此数据(String param1,String param2)

public static MyFragment newInstance(String param1, String param2) {
        MyFragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }
Run Code Online (Sandbox Code Playgroud)

然后在onCreate片段方法中你将获得数据:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }
Run Code Online (Sandbox Code Playgroud)

所以现在mParam1有data1mParam2有data2

现在您可以 在片段中使用此mParam1mParam2.


Mar*_*tin 7

如果将对(具体的子类)片段的引用传递给异步任务,则可以直接访问该片段.

将片段引用传递给异步任务的一些方法:

  • 如果你的异步任务是一个完全成熟的类(class FooTask extends AsyncTask),那么将你的片段传递给构造函数.
  • 如果异步任务是内部类,只需在作用域中声明最终的Fragment变量,定义异步任务,或者作为外部类的字段.您将能够从内部类访问它.


fra*_*lbo 7

有时您可以在您的活动中接收 Intent,您需要将信息传递给您的工作片段。
如果您需要启动片段,给出的答案是可以的,但如果它仍在工作,setArguments()则不是很有用。
如果传递的信息会导致与您的 UI 交互,则会出现另一个问题。在这种情况下,你不能调用类似的东西,myfragment.passData()因为 android 会很快告诉只有创建视图的线程才能与之交互。

所以我的建议是使用接收器。这样,您可以从任何地方发送数据,包括活动,但工作将在片段的上下文中完成。

在你的片段中onCreate()

protected DataReceiver dataReceiver;
public static final String REC_DATA = "REC_DATA";

@Override
public void onCreate(Bundle savedInstanceState) {


    data Receiver = new DataReceiver();
    intentFilter = new IntentFilter(REC_DATA);

    getActivity().registerReceiver(dataReceiver, intentFilter);
}

private class DataReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        int data= intent.getIntExtra("data", -1);

        // Do anything including interact with your UI
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的活动中:

// somewhere
Intent retIntent = new Intent(RE_DATA);
retIntent.putExtra("data", myData);
sendBroadcast(retIntent);
Run Code Online (Sandbox Code Playgroud)


Adr*_*ica 7

我想为初学者补充一点,此处两个最受好评的答案之间的差异是由片段的不同用法引起的。

如果在java类中使用要传递数据的片段,则可以将第一个答案应用于传递数据:

Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
Run Code Online (Sandbox Code Playgroud)

但是,如果您使用例如Android Studio提供的用于选项卡式片段的默认代码,则此代码将不起作用。

如果你与你FragmentClasses替换默认PlaceholderFragment它甚至不会工作,即使你纠正FragmentPagerAdapter到)新形势下增加了对的getItem(开关和另一个开关getPageTitle()(如图所示这里

警告:上面提到的剪辑存在代码错误,我将在后面在此处进行解释,但是对于查看如何从默认代码转到选项卡式片段的可编辑代码很有用)!如果您考虑该剪辑中的Java类和xml文件,则剩下的答案就更有意义了(代表初学者场景中第一次使用选项卡式片段)。

此页面上投票率最高的答案将不起作用的主要原因是,在该选项卡式片段的默认代码中,这些片段用于另一个Java类:FragmentPagerAdapter!

因此,为了发送数据,您很想在MotherActivity中创建一个包,然后使用答案2将其传递到FragmentPagerAdapter中。

只是那又是错的。(也许您可以那样做,但这只是一个复杂的操作,实际上并不需要)。

我认为,正确/简便的方法是使用答案2将数据直接传递到有问题的片段。是的,对于选项卡式片段,活动与片段之间会紧密结合,这是我们所期望的。我什至建议您在MotherActivity java类内创建选项卡式片段(作为子类,因为它们永远不会在MotherActivity外使用)-很简单,只需在MotherActivity java类内添加所需的多个片段,如下所示:

 public static class Tab1 extends Fragment {

    public Tab1() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
        return rootView;
    }
}.
Run Code Online (Sandbox Code Playgroud)

因此,要将数据从MotherActivity传递到这样的片段,您将需要在Mother活动的onCreate上方创建私有的字符串/捆绑-您可以填充要传递给片段的数据,然后通过在onCreate之后创建的方法(此处称为getMyData())。

public class MotherActivity extends Activity {

    private String out;
    private Bundle results;

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

       // for example get a value from the previous activity
        Intent intent = getIntent();
        out = intent.getExtras().getString("Key");

    }

    public Bundle getMyData() {
        Bundle hm = new Bundle();
        hm.putString("val1",out);
        return hm;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在fragment类中,使用getMyData:

public static class Tab1 extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public Tab1() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
            TextView output = (TextView)rootView.findViewById(R.id.your_id_for_a_text_view_within_the_layout);

            MotherActivity activity = (MotherActivity)getActivity();

            Bundle results = activity.getMyData();
            String value1 = results.getString("val1");

            output.setText(value1);
            return rootView;
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果您有数据库查询,我建议您在MotherActivity中进行查询(并将它们的结果作为附加在捆绑包内的键上的字符串/整数传递,如上所示),就像在选项卡式片段中一样,您的语法将变得更加复杂(这将成为getActivity (),而getIntent变为getActivity()。getIntent),但您也可以选择执行自己的操作。

我对初学者的建议是专注于小步骤。首先,您打算打开一个非常简单的选项卡式活动,而不传递任何数据。它行得通吗?它会打开您期望的标签吗?如果没有,为什么?

从此开始,并通过应用解决方案(如本剪辑中介绍的解决方案),了解缺少的内容。对于该特定剪辑,永远不会显示mainactivity.xml。那肯定会让您感到困惑。但是如果您注意的话,您会看到例如xml片段文件中的上下文(tools:context)错误。每个片段XML需要指向正确的片段类(或使用分隔符$的子类)。

您还将看到在主活动Java类中,需要添加tabLayout.setupWithViewPager(mViewPager)-在TabLayout ==(TabLayout)findViewById(R.id.tabs);行之后。如果没有此行,则您的视图实际上未链接到片段的XML文件,但仅显示了主要活动的xml文件。

除了主要活动java类中的行之外,还需要在主要活动XML文件中更改选项卡以适合您的情况(例如,添加或删除TabItems)。如果主活动XML中没有选项卡,那么当您首先创建它时(新活动-选项卡式活动),可能没有选择正确的活动类型。

请注意,在最后三段中,我将介绍视频!因此,当我说主要活动XML时,它就是视频中的主要活动XML,在您情况下,它就是MotherActivity XML文件。


小智 6

Activity您使用 Bundle 发送数据为:

Bundle bundle = new Bundle();
bundle.putString("data", "Data you want to send");

// Your fragment
MyFragment obj = new MyFragment();
obj.setArguments(bundle);
Run Code Online (Sandbox Code Playgroud)

并在FragmentonCreateView 方法中获取数据:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{
    String data = getArguments().getString("data");// data which sent from activity  
    return inflater.inflate(R.layout.myfragment, container, false);
}
Run Code Online (Sandbox Code Playgroud)


sbe*_*zin 5

很老的帖子,我仍然敢于添加一些对我有帮助的解释。

从技术上讲,您可以直接在活动的片段中设置任何类型的成员。
那么为什么要捆绑呢?
原因很简单——Bundle 提供了统一的处理方式:
——创建/打开片段
——重新配置(屏幕旋转)——只需在 onSaveInstanceState() 中将初始/更新包添加到 outState——
应用程序在后台被垃圾收集后恢复(与重新配置一样)。

你可以(如果你喜欢实验)在简单的情况下创建一个解决方法,但捆绑方法只是看不到一个片段和一个 backstack 上的一千个片段之间的区别 - 它保持简单明了。
这就是为什么@Elenasys的答案是最优雅和通用的解决方案。
这就是@Martin给出的答案存在缺陷的原因


小智 5

如果activity需要fragment在初始化后执行一个动作,最简单的方法是activityfragment实例调用一个方法。在 中fragment,添加一个方法:

public class DemoFragment extends Fragment {
  public void doSomething(String param) {
      // do something in fragment
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在 中activity,访问fragment使用fragment管理器并调用method

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DemoFragment fragmentDemo = (DemoFragment) 
            getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
        fragmentDemo.doSomething("some param");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后activity可以fragment通过调用 this直接与 通信method

  • 这真的很好,因为您不想进入片段中的 `onCreateView` 方法。真的很有帮助 (3认同)