Bir parça ve kap aktivitesi arasında veri aktarımı


176

Bir parça ve kap aktivitesi arasında nasıl veri aktarabilirim? Veriler arasında etkinlikler yoluyla veri aktarmaya benzer bir şey var mı?

Bunu okudum, ama çok yardımcı olmadı:
http://developer.android.com/guide/topics/fundamentals/fragments.html#CommunicatingWithActivity


Bu yetersiz mi? İstediğin her şeyi gönderebilirsin, belki daha fazlasını açıklayabilirsin, ne yapmak istersin?
Marcin Milejski

Belgeden, örneğin, aktiviteden parçaya veya bir dizeden nasıl bir değer veya dize geçireceğimi anlamadım. Teşekkürler
tyb

2
Parçalardan eşzamansız çağrıları ele almanın ve onlara veri döndürmenin en iyi yolu her iki tarafa BroadcastReceivers uygulamaktır. Spesifik olmayan sayıda parça ile çalışıyorsanız, yine de eşzamansız hale getirmelisiniz.
Marek Sebera

@punisher_malade Hayır, benim için çalışıyor
Vadim Kotov

Yanıtlar:


211

Parçanızdan arayabilirsiniz getActivity().

Bu, parçayı oluşturan etkinliğe erişmenizi sağlayacaktır. Buradan, etkinlikte olan herhangi bir erişimci yöntemini çağırabilirsiniz.

getResult()Faaliyetinizde çağrılan bir yöntem için:

((MyActivity) getActivity()).getResult();

86
Etkinliğiniz içinde (üst Android etkinliğinde değil) bir işleve eriştiğiniz için getActivity () çağrınızı yayınlamanız gerekir: ((MyActivity) getActivity ()). GetResult ();
Nick

3
Parçadan aktiviteye geri dönüş yöntemi nasıl olacak?
Vasil Valchev

6
@VasilValchev, bir arabirim oluşturabilir ve etkinliği onu uygulamaya zorlayabilir ve daha sonra verileri aktarmak için parçanızdan bir yöntem çağırabilirsiniz. Etkinliğin arabirimi uygulayıp uygulamadığını kontrol etmek için onAttach yöntemini kullanın.
Ivan Nikolov

3
@IvanNikolov'dan mükemmel cevap. Fragments Eğitim Bağlantısında
bogdan

8
Bu iyi bir uygulama ya da kalıp değildir. Arayüzlerle cevap doğru.
moictab

303

Arayüzleri kullanmayı deneyin.

Verileri içeren etkinliğine geri iletmesi gereken herhangi bir parça, verileri işlemek ve iletmek için bir arabirim bildirmelidir. Ardından, içerme etkinliğinizin bu arabirimleri uyguladığından emin olun. Örneğin:

JAVA

Parçanızda arayüzü bildirin ...

public interface OnDataPass {
    public void onDataPass(String data);
}

Daha sonra, kapsayıcı sınıfın uygulanmasını onAttach yöntemindeki parçaya bağlayın, şöyle:

OnDataPass dataPasser;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    dataPasser = (OnDataPass) context;
}

Parçanızın içinde, veri geçişini işlemeniz gerektiğinde, bunu dataPasser nesnesinde çağırmanız yeterlidir:

public void passData(String data) {
    dataPasser.onDataPass(data);
}

Son olarak, uygulayan aktivitenizde OnDataPass...

@Override
public void onDataPass(String data) {
    Log.d("LOG","hello " + data);
}

KOTLIN

1. Adım. Arabirim Oluşturun

interface OnDataPass {
    fun onDataPass(data: String)
}

2. Adım. Ardından, kapsayıcı sınıfın arabirim uygulamasını onAttach yöntemindeki (YourFragment) parçasına bağlayın, şöyle:

lateinit var dataPasser: OnDataPass

override fun onAttach(context: Context) {
    super.onAttach(context)
    dataPasser = context as OnDataPass
}

Adım 3. Parçanızın içinde, veri geçişini işlemeniz gerektiğinde, bunu dataPasser nesnesinde çağırmanız yeterlidir:

fun passData(data: String){
    dataPasser.onDataPass(data)
}

Adım 4. Son olarak, etkinliğinizde OnDataPass uygular

class MyActivity : AppCompatActivity(), OnDataPass {}

override fun onDataPass(data: String) {
    Log.d("LOG","hello " + data)
}

1
Bu noktaya teşekkürler, iyi cevap. Bu da burada çok güzel açıklanıyor . Fark etmediğim şey, birden fazla arabirim uygulayabildiğiniz, zaten bir uygulama yapıyordum ActionBar.TabListenerve ek bir arayüz eklemek zorunda kaldım.
Eugene van der Merwe

5
Bu kesinlikle gitmek için bir yol ve bence gitmek için tek yol. Etkinlik ve Fragman arasında iki yönlü etkileşim sağlar. Ayrıca, sekmelerden veya çoklu fragman düzeninden oluşan bir etkinlikte birden fazla fragmanınız olduğunda bir aracın fragmanlar arasında iletişim kurmasına izin verir.
Christopher

1
Merak ettiğim bir şey var ... Bu resmi cevap ve resmi geliştirici sitesinden, bunun frag-act-frag'ı iletişim kurmak için doğru yol olduğunu söylüyorlar, ancak getActivity ( )?
unmultimedio

3
Neden birisinin bunu yapmak için ekstra bir arayüze ihtiyacı var? Aşağıdaki çözümü neden kötü veya çözümünüzü daha iyi buluyorsunuz? ((MyActivity) getActivity) .myMethod (...)
spacifici

3
onAttach (Etkinlik etkinliği) kullanımdan kaldırıldı, lütfen bunun yerine onAttach (Bağlam içeriği) kullanın.
Chris.C

23

En Kolay Yaklaşım ancak Önerilmez

Etkinlik verilerine parçadan erişebilirsiniz:

Aktivite:

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

Fragment:

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

5
Bu, kodunuza yüksek bağlantı ekler ve kötü bir uygulamadır. Şimdi MyActivity
Parçayı

neden bu yol kötü bir uygulama olarak görülüyor ve arayüz sadece bu sorunun çözümü mü?
androidXP

Tüm etkinlik bir BaseActivity'den genişliyorsa veya bunu BaseActivity activity = (BaseActivity) getActivity () gibi yayınlarsak AmeyaB; o zaman tüm faaliyetler üzerinde çalışacaktır
Zar E Ahmer

21
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Bundle b = getActivity().getIntent().getExtras();
            wid = b.getString("wid");
            rid = b.getString("rid");
            View view = inflater.inflate(R.layout.categoryfragment, container, false);
    return view;
 }

14
Parçada bu şekilde elde edersiniz, ancak parçanızı xml mizanpaj dosyasında varsa, parçayı çağıran sınıfta nasıl ayarlarsınız.
Zapnologica

17

Bir parça ve kap aktivitesi arasında veri aktarımı

Aktivite:

        Bundle bundle = new Bundle();
        bundle.putString("message", "Alo Elena!");
        FragmentClass fragInfo = new FragmentClass();
        fragInfo.setArguments(bundle);
        transaction.replace(R.id.fragment_single, fragInfo);
        transaction.commit();

Fragment:

Parçadaki değeri okuma

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

merhaba @Elenasys. Paket verilerini etkinlikten parçaya nasıl geri gönderebilirim. Parçadan aktiviteye gittim ve zaten yaratılmış olan parçaya geri dönmem gerekiyor (sadece onStart, onResume, ... çağırıyor) ve aktivite olarak elde edebildiğim verilere ihtiyacım var. Bunu yapmanın bir yolu var mı yoksa yanlış bir şey mi yapıyorum?
Michal Moravik

7

Bunun en iyi yol olup olmadığını bilmiyorum Bu oldukça uzun bir süredir google üzerinde arama yapıyorum Bir parçayı konteyner etkinliğine nasıl bir paket gönderebilirim ama bulduğum tek şey bunun yerine etkinlikten parçaya veri gönderiyordu (Bu bir acemi olduğum için benim için biraz kafa karıştırıcıydı).

daha sonra istediğim gibi benim için çalışan bir şey denedim. bu yüzden benim gibi birinin de aynı şeyi aradığını yazacağım.

// Parçadan veri iletme.

Bundle gameData = new Bundle();
        gameData.putStringArrayList(Constant.KEY_PLAYERS_ARR,players);
        gameData.putString(Constant.KEY_TEAM_NAME,custom_team_name);
        gameData.putInt(Constant.KEY_REQUESTED_OVER,requestedOver);

        Intent intent = getActivity().getIntent();
        intent.putExtras(gameData);

// Paketten kapsayıcı etkinliğinden veri alma.

Bundle gameData = getIntent().getExtras();
        if (gameData != null)
        {
            int over = gameData.getInt(Constant.KEY_REQUESTED_OVER);
            ArrayList<String> players = gameData.getStringArrayList(Constant.KEY_PLAYERS_ARR);
            String team = gameData.getString(Constant.KEY_TEAM_NAME);

        }
        else if (gameData == null)
        {
            Toast.makeText(this, "Bundle is null", Toast.LENGTH_SHORT).show();
        }

6

Arayüz en iyi çözümlerden biridir:

Tutkal Arayüzü:

public interface DataProviderFromActivity {

    public String getName();
    public String getId);

}  

Benim faaliyetim:

public class MyActivity implements DataProviderFromActivity{

    String name = "Makarov";
    String id = "sys533";

    ... ... ... ... ... .... .... 
    ... ... ... ... ... .... .... 

    public String getName(){
        return name;
    };
    public String getId(){
        return id;
    };
}

MyFragment:

public class MyFragment extends Fragment{

    String fragName = "";
    String fragId = "";

    ... ... ... ... ... .... .... 
    ... ... ... ... ... .... .... 

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        DataProviderFromActivity myActivity= (DataProviderFromActivity) getActivity();
        fragName = myActivity.getName();
        fragId = myActivity.getId();

        ... ... ... ... ... .... .... 
        ... ... ... ... ... .... .... 

        updateFragmentView();
    }
}

Merhaba @HassanMakarov Arayüzünü beğendim, basit ve temiz. Yine de bir sorunum var. Benim viewpager için özel olup olmadığını bilmiyorum ama bir kerede en fazla 2 parça veri almak? "Makarov" & "sys533" dizeleri, etkinlik oluşturulduğunda 1 ve 2 numaralı parçalarda görünür ancak 2 ya da 3 numaralı parça seçilene kadar dizeler 3. parçada görünmez mi? Herhangi bir fikir?
JC23

@ JC23 Sanırım sorun parça işlemiyle ilgili. MainActivity başlatıldığında hangi parça ayarlanır?
Hassan Tareq

@ JC23 Yaptığım şey: Tab / ViewPager yerine Araç Çubuğu ve NavigationView kullanıyorum. OnNavigationItemSelected () 'de parçaları uygun şekilde ayarlamak için parça işlemleri gerçekleştiriyorum.
Hassan Tareq

2

Tarih Dinleyicilerini uygulayan bir AppCompatActivity kullandım. Bir tarih aralığı seçiciyi kodlamam gerektiğinden parçalar bir zorunluluk olarak geldi. Ayrıca, kapsayıcıya bunları ana etkinliğe geri döndürmek için seçilen tarihleri ​​alması gerekiyordu.

Kapsayıcı etkinliği için bu, sınıf bildirimidir:

public class AppCompatDateRange extends AppCompatActivity implements
    DateIniRangeFragment.OnDateIniSelectedListener, DateFimRangeFragment.OnDateFimSelectedListener

Ve geri aramalar için arayüzler:

@Override
public void onDateIniSelected(String dataIni) {
    Log.i("data inicial:", dataIni);
}

@Override
public void onDateFimSelected(String dataFim) {
    Log.i("data final:", dataFim);
}

Geri aramalar dizelerdir, çünkü tarihler bir sorgu seçimindeki parametrelerdir.

Parçaların kodu (ilk tarih parçasına göre):

public class DateIniRangeFragment extends Fragment {
OnDateIniSelectedListener callbackIni;

private DatePicker startDatePicker;

public DateIniRangeFragment() {
    ///required empty constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

///through this interface the fragment sends data to the container activity
public interface OnDateIniSelectedListener {
    void onDateIniSelected(String dataIni);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ///layout for the fragment
    View v = inflater.inflate(R.layout.date_ini_fragment, container, false);

    ///initial date for the picker, in this case, current date
    startDatePicker = (DatePicker) v.findViewById(R.id.start_date_picker_appcompat);
    Calendar c = Calendar.getInstance();
    int ano = c.get(Calendar.YEAR);
    int mes = c.get(Calendar.MONTH);
    int dia = c.get(Calendar.DAY_OF_MONTH);
    startDatePicker.setSpinnersShown(false);
    startDatePicker.init(ano, mes, dia, dateSetListener);

    return v;
}

///listener that receives the selected date
private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() {
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        if (view.isShown()) { ///if the datepicker is on the screen
            String sDataIni = year + "-" + (monthOfYear + 1) + "-" + dayOfMonth;
            callbackIni.onDateIniSelected(sDataIni); //apply date to callback, string format
        }
    }
};

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    /*
    * this function guarantees that the container activity implemented the callback interface
    * */
    try {
        callbackIni = (OnDateIniSelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " deve implementar OnDateIniSelectedListener");
    }
}

}

Kap + parçaları oluşturmak için, FragmentPagerAdapter'ı genişleten özel bir sınıfla bir ViewPager (AppCompat) kullandım. İletişim kutusu yok.


2

EventBus'u kullanabilirsiniz , kolaydır ve harika çalışır

3 adımda EventBus

  1. Olayları tanımlayın:

    public static class MessageEvent { /* Additional fields if needed */ }

  2. Aboneler hazırlayın: Abone olma yönteminizi beyan edin ve açıklama ekleyin, isteğe bağlı olarak bir iş parçacığı modu belirtin:

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {/* Do something */};

Abonenizi kaydedin ve kaydını kaldırın. Örneğin, Android'de etkinlikler ve fragmanlar genellikle yaşam döngülerine göre kaydolmalıdır:

 @Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }
  1. Etkinlik yayınla:

    EventBus.getDefault().post(new MessageEvent());



0

Bu benim için çalışıyor ..

Etkinlik'te bu yöntemi ekleyin

    public void GetData(String data)
     {
        // do something with your data        
     }

ve Fragment'a bu satırı ekleyin

((YourActivity)getContext).GetData("your data here");

0
public class Fragmentdemo extends Fragment {

  public interface onDemoEventListener {
    public void demoEvent(String s);
  }

  onDemoEventListener demoEventListener;

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
        try {
          demoEventListener = (onDemoEventListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement onDemoEventListener");
        }
  }

  final String LOG_TAG = "TAG";

  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragmentdemo, null);

    Button button = (Button) v.findViewById(R.id.button);
    button.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        demoEventListener.someEvent("Test text to Fragment1");
      }
    });
    enter code here
    return v;
  }
}

-12

Başka bir etkinlikten aktarılan verileri bir konteyner etkinliğindeki bir parça halinde almanın başka bir basit yolu: örneğin:

Etkinlik_A => Etkinlik_B (Parça)

Etkinlik_A'nızda başka bir etkinliğe veri gönderiyor gibi bir niyet oluşturursunuz:

Intent intent = new Intent(getBaseContext(),Activity_B.class);
intent.putExtra("NAME", "Value");
startActivity(intent);

Etkinlik_B'nizde bulunan Parçanızda:

String data = getActivity().getIntent().getExtras();

getBaseContext()bana şu hatayı veriyor:The method getBaseContext() is undefined for the type new View.OnClickListener(){}
Si8
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.