web-dev-qa-db-ja.com

Androidのアクティビティからフラグメントにデータを送信する

私は2つのクラスがあります。 1つはアクティビティ、もう1つは私がEditTextを持っているフラグメントです。アクティビティではasync-taskを持つサブクラスがあり、メソッドdoInBackgroundではいくつかの結果が出ます。それを変数に保存します。この変数をサブクラス "my activity"からこのフラグメントに送るにはどうすればいいですか?

264
user1302569

Activityから、意図的にデータを送信します。

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

そしてフラグメントonCreateViewメソッドで:

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

フラグメントからアクティビティデータにアクセスすることもできます。

活動:

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

私はここに多くの答えを見つけました@ 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");
        ...
        ...
        ...
        }
41
Elenasys

この答えは遅すぎるかもしれません。しかしそれは将来の読者には役に立つでしょう。

いくつかの基準があります。意図的にファイルを選ぶようにコーディングしました。さらなる処理のために特定のフラグメントに渡されるファイルを選択しました。私はファイルピッキングの機能を持つ多くのフラグメントを持っています。当時は、条件をチェックしてフラグメントを取得して値を渡すたびに、かなり嫌です。だから、私はインタフェースを使用して値を渡すことにしました。

ステップ1: Main Activityでインタフェースを作成します。

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

ステップ2: 同じアクティビティにメソッドを作成する

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

ステップ3: 同じアクティビティにSelectedBundle参照を作成する

   SelectedBundle selectedBundle;

ステップ4: すべてのフラグメントがファイルピッカー機能を必要とするSelectedBundle参照を初期化する必要があります。このコードをあなたのフラグメントonCreateView(..)メソッドに配置してください。

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

ステップ5:MainActivityから onActivityResultに、interfaceを使用して値をフラグメントに渡します。

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

それで全部です。必要なすべてのフラグメントをFragmentClassに実装します。あなたは素晴らしいです。あなたはやった。ワオ...

14
Noorul

Fragments(F)を使用する基本的なアイデアは、Androidアプリケーションで再利用可能な自立型のUIコンポーネントを作成することです。これらのフラグメントはアクティビティに含まれており、A - > FおよびF-Aからコミュニケーションパスを作成する一般的な(最善の)方法があります。フラグメントのみが分離されて自立するので、アクティビティを通してF-F間で通信する必要があります。

それでA - > Fからデータを渡すことはρяσερєяKによって説明されるのと同じことになるでしょう。その答えに加えて、Activityの中でFragmentsを作成した後に、Fragmentsでメソッドを呼び出すフラグメントにデータを渡すこともできます。

例えば:

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

最も便利で便利な方法は、フラグメントインスタンスを呼び出してその時点でデータを送信することです。 デフォルトではすべてのフラグメントにインスタンスメソッドがあります

たとえば、フラグメント名がMyFragmentの場合

だからあなたはこのような活動からあなたのフラグメントを呼び出すでしょう:

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

* R.id.containerは私のFrameLayoutのIDです

だからMyFragment.newInstance( "data1"、 "data2")あなたはfragmentにデータを送ることができ、あなたの断片の中であなたは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がdata1mParam2がdata2

これで、フラグメント内でこのmParam1mParam2を使用できます。

10
Pre_hacker

フラグメント(の具体的なサブクラス)への参照を非同期タスクに渡すと、そのフラグメントに直接アクセスできます。

フラグメント参照を非同期タスクに渡す方法はいくつかあります。

  • 非同期タスクが本格的なクラス(class FooTask extends AsyncTask)である場合は、フラグメントをコンストラクタに渡します。
  • 非同期タスクが内部クラスの場合は、非同期タスクが定義されているスコープ内で、または外部クラスのフィールドとして、最後のFragment変数を宣言するだけです。あなたは内部クラスからそれにアクセスすることができるでしょう。
7
Martin

ActivityからBundleを使用してデータを送信します。

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

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

そしてフラグメントの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);
}
4
Vijay

非常に古い投稿ですが、それでも私は私に役立つはずだった小さな説明を追加することを敢えてします。

技術的には、アクティビティーからのフラグメントに任意のタイプのメンバーを直接設定できます。
では、なぜバンドルするのですか。
その理由は非常に単純です - Bundleは統一された処理方法を提供します。
- フラグメントを作成する/開く
- 再構成(画面の回転) - onSaveInstanceState()でoutStateに初期/更新されたバンドルを追加するだけです
- バックグラウンドでガベージコレクションされた後のアプリの復元(再構成の場合と同様)。

(実験が好きなら)単純な状況で回避策を作成することができますが、Bundleアプローチではバックスタック上の1つのフラグメントと1000の違いを見ることはできません。
だからこそ @Elenasys による答えが最も洗練された普遍的な解決策です。
そして、それが @Martin によって与えられる答えが 落とし穴を持つ理由

4
sberezin

私がここで2つの最も支持された答えの間の違いが断片の異なる使い方によって与えられることを初心者に付け加えたいです。

渡すデータがあるJavaクラス内でフラグメントを使用する場合は、最初の回答を適用してデータを渡すことができます。

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

ただし、たとえばタブ付きフラグメントに対してAndroid Studioによって提供されているデフォルトコードを使用すると、このコードは機能しません。

デフォルトのPlaceholderFragmentをFragmentClassesに置き換えても、またFragmentPagerAdapterを新しい状況に修正してもgetItem()用のスイッチとgetPageTitle()用のスイッチを追加しても機能しません( here )。

警告:上記のクリップにはコードエラーがあります。これについては後で説明しますが、デフォルトのコードからタブ付きフラグメントの編集可能コードへの変更方法を確認するのに役立ちます。私の答えの残りの部分は、そのクリップのJavaクラスとxmlファイル(初心者のシナリオによるタブ付きフラグメントの最初の使用の代表)を考えた場合、はるかに理にかなっています。

このページで最も支持されている答えがうまくいかない主な理由は、タブ付きフラグメントのデフォルトコードでは、フラグメントが別のJavaクラスで使用されていることです。FragmentPagerAdapter!

そのため、データを送信するには、答え2を使用して、MotherActivityでバンドルを作成し、それをFragmentPagerAdapterに渡します。

それだけがまた間違っています。 ( たぶんあなたはそのようにそれをすることができました、しかしそれは本当に必要とされていない単なる複雑さです )。

そのための正しい/簡単な方法は、答え2を使って、問題のフラグメントにデータを直接渡すことです。はい。タブ付きフラグメントの場合、アクティビティとフラグメント(BUT)との間に密接な関係があります。 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の上にプライベートなStrings/Bundlesを作成する必要があります。これには、フラグメントに渡したいデータを入力して、 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;
    }
}

そしてフラグメントクラスでは、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になります)。たとえば、getIntentはgetActivity()。getIntent)になりますが、必要に応じて実行することもできます。

私の初心者へのアドバイスは小さなステップに集中することです。まず、データを一切渡さずに、非常に単純なタブ付きアクティビティを開くようにします。動作しますか?それはあなたが期待するタブを開きますか?そうでない場合、なぜですか?

それから始めて、 このクリップ にあるような解決策を適用することによって、何が足りないのかを見てください。その特定のクリップでは、mainactivity.xmlは表示されません。それはきっとあなたを混乱させるでしょう。しかしあなたが注意を払うならば、あなたは例えばコンテキスト(tools:context)がxmlフラグメントファイルで間違っているのを見るでしょう。各フラグメントXMLは正しいフラグメントクラス(またはセパレータ$を使用したサブクラス)を指す必要があります。

また、メインアクティビティのJavaクラスで、tabLayout.setupWithViewPager(mViewPager)を追加する必要があることもわかります - TabLayout tabLayout =(TabLayout)findViewById(R.id.tabs);この行がないと、ビューは実際にはフラグメントのXMLファイルにリンクされていませんが、メインアクティビティのxmlファイルのみが表示されます。

メインアクティビティのJavaクラスの行に加えて、メインアクティビティのXMLファイルでは、状況に合わせてタブを変更する必要があります(たとえば、TabItemの追加または削除)。メインアクティビティXMLにタブがない場合は、最初に作成したときに正しいアクティビティタイプを選択しなかった可能性があります(新しいアクティビティ - タブ付きアクティビティ)。

最後の3段落で私はビデオについて話していることに注意してください。ですから、私がメインアクティビティXMLと言ったとき、それはビデオのメインアクティビティXMLです。あなたの状況では、それはMotherActivity XMLファイルです。

4
Adrian Stoica

時々あなたはあなたの活動の中で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);
3
fralbo

アクティビティクラスからフラグメントにデータを送信するためのより良い方法は、セッターメソッドを介して渡すことです。好き

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

そしてこれらのデータをクラスから簡単に取得します。

3
ssi-anik

そのフラグメントの静的参照を取得してその関数にデータを渡し、同じメソッドの引数にそのデータを設定し、そのフラグメントのoncreateメソッドでgetArgumentを介してデータを取得し、そのデータをlocalに設定するpublic staticメソッドを作成することができます。変数.

1
M.Noman

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と直接通信できます。

1
user4813855

以下のインタフェースを使ってアクティビティとフラグメントの間のコミュニケーションをとる

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

フラグメントショーメソッド

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

onAttach(Context)でもGenericConnectorにコンテキストをキャストできます

あなたの活動に

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();のように使用しないでください。

1
Qamar

私の解決策は、フラグメント内に静的メソッドを書くことです。

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

こうすれば、私が必要とするすべてのデータは、それを処理するために必要となる可能性のある他の操作の前に、そのフラグメントの内部にあることが確実になります。私の考えではそれもきれいに見えます。

0
Matteo

上記の方法のほとんどが機能する一方で、この質問に出くわしました。特に、コンポーネント(アクティビティまたはフラグメント)が作成されていないシナリオでは、 Event Bus Library を使用できることを追加したいと思います。これはAndroidのすべてのサイズに適していますプロジェクトと多くのユースケース。私は個人的にプレイストアで持っているいくつかのプロジェクトでそれを使用しました。

0
Joshua Majebi

フラグメントとアクティビティの間でデータをやり取りするための最も賢い方法でテストされた方法は、変数を作成することです。

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の値を入手できます。がんばろう!

0
Andrew Sam

最新のナビゲーションアーキテクチャコンポーネントを使用しているときに、私は同様の問題に遭遇しました。私の呼び出し元のアクティビティからFragmentにバンドルを渡すことで、上記のすべてのコードを試してみました。

Androidの最新の開発動向に従った最善の解決策は、View Model(Android Jetpackの一部)を使用することです。

親ActivityでViewModelクラスを作成して初期化します。このViewModelはアクティビティとフラグメントの間で共有する必要があります。

これで、フラグメントのonViewCreated()内で、同じViewModelを初期化し、ViewModelフィールドを監視するようにObserversを設定します。

必要に応じて、役に立つ、詳細なチュートリアルを紹介します。

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

0
devDeejay