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

时间:2012-10-05 05:15:04

标签: android android-fragments

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

22 个答案:

答案 0 :(得分:568)

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

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

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

答案 1 :(得分:95)

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

<强>活动:

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

<强>片段:

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

答案 2 :(得分:41)

我在这里找到了很多答案@ 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();

<强>片段:

读取片段中的值

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

或只是

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

答案 3 :(得分:15)

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

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

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

   public interface SelectedBundle {
    void onBundleSelect(Bundle bundle);
   }

第2步:在相同活动

上创建SelectedBundle引用
   SelectedBundle selectedBundle;

第3步:在同一活动中创建方法

   public void setOnBundleSelected(SelectedBundle selectedBundle) {
       this.selectedBundle = selectedBundle;
   }

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

    ((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() {
          @Override
         public void onBundleSelect(Bundle bundle) {
            updateList(bundle);
        }
     });

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

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

多数民众赞成。在FragmentClass上实现您需要的每个片段。你很棒。你做完了WOW ...

答案 4 :(得分:12)

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

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

例如:

    ArticleFragment articleFrag = (ArticleFragment)
                    getSupportFragmentManager().findFragmentById(R.id.article_fragment);
    articleFrag.updateArticleView(position);

答案 5 :(得分:10)

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

  

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

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

getSupportFragmentManager().beginTransaction().add(R.id.container, MyFragment.newInstance("data1","data2"),"MyFragment").commit();

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

所以在 MyFragment.newInstance(&#34; data1&#34;,&#34; data2&#34;)中,您可以将数据发送到片段,在片段中,您可以在< strong> 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;
    }

然后在片段的 onCreate 方法中获取数据:

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

所以现在 mParam1有data1 mParam2有data2

     

现在您可以在片段中使用此 mParam1 mParam2

答案 6 :(得分:7)

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

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

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

答案 7 :(得分:4)

从活动中您使用Bundle发送数据为:

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

// Your fragment
MyFragment obj = new MyFragment();
obj.setArguments(bundle);

在Fragment onCreateView方法中获取数据:

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

答案 8 :(得分:4)

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

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

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

答案 9 :(得分:4)

我想为初学者补充说,这里有两个最受欢迎的答案之间的差异是由片段的不同用法给出的。

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

Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

但是,如果您使用Android Studio为标签片段提供的默认代码,则此代码将无效。

即使你用FragmentClasses替换默认的PlaceholderFragment也行不通,即使你将FragmentPagerAdapter更正为新的情况,为getItem()添加一个开关,为getPageTitle()添加另一个开关(如图所示{{3} })

警告:上面提到的剪辑有代码错误,我将在后面解释,但是看看如何从默认代码转换为标签片段的可编辑代码非常有用!如果您考虑该剪辑中的java类和xml文件(代表初学者场景首次使用选项卡式片段),我的其余部分会更有意义。

此页面中最受欢迎的答案的主要原因是,在标签片段的默认代码中,片段用于另一个java类:FragmentPagerAdapter!

因此,为了发送数据,您很想在MotherActivity中创建一个包,并使用第二个答案在FragmentPagerAdapter中传递它。

只有那是错误的。 (也许你可以这样做,但它只是一个并不真正需要的复杂功能)。

我认为,正确/更简单的方法是使用答案2将数据直接传递给相关片段。 是的,Activity和Fragment之间会有紧密耦合,但是对于标签片段,这是预期的。我甚至建议你在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;
    }
}.

因此,要将数据从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;
    }
}

然后在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;
        }
    }

如果您有数据库查询,我建议您在MotherActivity中执行它们(并将结果作为附加到包内的键的字符串/整数传递,如上所示),因为在选项卡式片段内部,您的语法将变得更加复杂(例如,getActivity()变为getActivity(),getIntent变为getActivity(。getIntent),但您也可以选择按照自己的意愿进行。

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

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

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

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

请注意,在最后3段中,我谈到了视频!因此,当我说主要活动XML时,它是视频中的主要活动XML,在您的情况下是MotherActivity XML文件。

答案 10 :(得分:3)

将数据从活动类发送到片段的更好方法是通过setter方法传递。喜欢

FragmentClass fragmentClass = new FragmentClass();
fragmentClass.setMyList(mylist);
fragmentClass.setMyString(myString);
fragmentClass.setMyMap(myMap);

轻松从课堂上获取这些数据。

答案 11 :(得分:3)

有时您可以在活动中收到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
    }
}

在你的活动中:

// somewhere
Intent retIntent = new Intent(RE_DATA);
retIntent.putExtra("data", myData);
sendBroadcast(retIntent);

答案 12 :(得分:2)

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

public class DemoFragment extends Fragment {
  public void doSomething(String param) {
      // do something in fragment
  }
}

然后在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");
    }
}

然后activity可以通过调用此fragment直接与method进行通信。

答案 13 :(得分:1)

您可以在片段中创建公共静态方法,您将获得该片段的静态引用,然后将数据传递给该函数并将该数据设置为相同方法中的参数,并通过片段的oncreate方法通过getArgument获取数据,并将其设置为数据到局部变量。

答案 14 :(得分:1)

使用以下界面在活动和片段

之间进行通信
public interface BundleListener {
    void update(Bundle bundle);
    Bundle getBundle();
}

或者使用跟随此通用侦听器进行使用接口

的双向通信
 /**
 * Created by Qamar4P on 10/11/2017.
 */
public interface GenericConnector<T,E> {
    T getData();
    void updateData(E data);
    void connect(GenericConnector<T,E> connector);
}

片段show方法

public static void show(AppCompatActivity activity) {
        CustomValueDialogFragment dialog = new CustomValueDialogFragment();
        dialog.connector = (GenericConnector) activity;
        dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
    }

您也可以将您的上下文转换为GenericConnector中的onAttach(Context)

在您的活动中

CustomValueDialogFragment.show(this);
片段中的

...
@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        connector.connect(new GenericConnector() {
            @Override
            public Object getData() {
                return null;
            }

            @Override
            public void updateData(Object data) {

            }

            @Override
            public void connect(GenericConnector connector) {

            }
        });
    }
...
    public static void show(AppCompatActivity activity, GenericConnector connector) {
            CustomValueDialogFragment dialog = new CustomValueDialogFragment();
            dialog.connector = connector;
            dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
        }

注意:切勿像"".toString().toString().toString();方式那样使用它。

答案 15 :(得分:1)

偶然发现了这个问题,而上面的大多数方法都可以使用。 我只想补充一下,您可以使用Event Bus Library,尤其是在尚未创建组件(活动或片段)的情况下,它适用于所有大小的android项目和许多用例。我曾在Playstore的多个项目中亲自使用过它。

答案 16 :(得分:0)

Smartest在片段和活动之间传递数据的尝试和测试方法是创建变量,例如:

class StorageUtil {
  public static ArrayList<Employee> employees;
}

然后,为了将数据从片段传递给活动,我们在onActivityCreated方法中执行此操作:

//a field created in the sending fragment
ArrayList<Employee> employees;

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
         employees=new ArrayList();

       //java 7 and above syntax for arraylist else use employees=new ArrayList<Employee>() for java 6 and below

     //Adding first employee
        Employee employee=new Employee("1","Andrew","Sam","1984-04-10","Male","Ghanaian");
        employees.add(employee);

      //Adding second employee
       Employee employee=new Employee("1","Akuah","Morrison","1984-02-04","Female","Ghanaian");
         employees.add(employee);

        StorageUtil.employees=employees;
    }

现在,您可以从任何地方获取StorageUtil.employees的值。 古德勒克!

答案 17 :(得分:0)

我的解决方案是在片段中编写一个静态方法:

public TheFragment setData(TheData data) {
    TheFragment tf = new TheFragment();
    tf.data = data;
    return tf;
}

这样我确信我需要的所有数据都在Fragment中,然后才能进行任何其他可能需要使用它的操作。 在我看来,它看起来更干净。

答案 18 :(得分:0)

在使用最新的导航架构组件时,我遇到了类似的问题。通过将捆绑包从我的调用活动传递到Fragment来试用所有上述代码。

遵循Android最新发展趋势的最佳解决方案是使用View Model(Android Jetpack的一部分)。

在父“活动”中创建并初始化ViewModel类,请注意,此ViewModel必须在活动和片段之间共享。

现在,在片段的onViewCreated()内部,初始化相同的ViewModel并设置观察者以侦听ViewModel字段。

如果需要,这里是有用的深入教程。

https://medium.com/mindorks/how-to-communicate-between-fragments-and-activity-using-viewmodel-ca733233a51c

答案 19 :(得分:0)

您可以在片段中创建setter方法。然后在“活动”中,当您引用片段时,您将调用setter方法,并将活动中的数据传递给它

答案 20 :(得分:0)

Kotlin 版本:

Activity中:

val bundle = Bundle()
bundle.putBoolean("YourKey1", true)
bundle.putString("YourKey2", "YourString")

val fragment = YourFragment()
fragment.arguments = bundle
val fragmentTransaction = parentFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.your_container, fragment, fragment.toString())
fragmentTransaction.commit()

Fragment onCreate() 中:

var value1 = arguments?.getBoolean("YourKey1", default true/false)
var value2 = arguments?.getString("YourKey2", "Default String")

答案 21 :(得分:-4)

在你的活动中声明静态变量

public static HashMap<String,ContactsModal> contactItems=new HashMap<String, ContactsModal>();

然后在你的片段中,请按照

ActivityName.contactItems.put(Number,contactsModal);