OnFragmentInteractionListener nasıl uygulanır


151

Ben android stüdyo 0.8.2 navigasyon çekmece ile bir sihirbaz oluşturulan uygulama var

Bir parça oluşturduk ve newInstance () ile ekledim ve bu hatayı alıyorum:

com.domain.myapp E / AndroidRuntime ﹕ FATAL İSTİSNA: ana java.lang.ClassCastException: com.domain.myapp.MainActivity@422fb8f0 OnFragmentInteractionListener uygulamalıdır

Nasıl bu OnFragmentInteractionListener uygulamak için hiçbir yerde bulamıyorum ?? Android SDK belgelerinde bile bulunamaz!

MainActivity.java

import android.app.Activity;

import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.widget.DrawerLayout;


public class MainActivity extends Activity
    implements NavigationDrawerFragment.NavigationDrawerCallbacks {

/**
 * Fragment managing the behaviors, interactions and presentation of the navigation drawer.
 */
private NavigationDrawerFragment mNavigationDrawerFragment;

/**
 * Used to store the last screen title. For use in {@link #restoreActionBar()}.
 */
private CharSequence mTitle;

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

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));
}

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();

    switch (position) {
        case 0: fragmentManager.beginTransaction()
                .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
                .commit(); break; 
        case 1: fragmentManager.beginTransaction() 
                .replace(R.id.container, AboutFragment.newInstance("test1", "test2"))
                .commit(); break; // this crashes the app
        case 2: fragmentManager.beginTransaction()
                .replace(R.id.container, BrowseQuotesFragment.newInstance("test1", "test2"))
                .commit(); break; // this crashes the app
    }
}


public void onSectionAttached(int number) {
    switch (number) {
        case 1:
            mTitle = getString(R.string.title_section1);
            break;
        case 2:
            mTitle = getString(R.string.title_section2);
            break;
        case 3:
            mTitle = getString(R.string.title_section3);
            break;
    }
}

public void restoreActionBar() {
    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setDisplayShowTitleEnabled(true);
    actionBar.setTitle(mTitle);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (!mNavigationDrawerFragment.isDrawerOpen()) {
        // Only show items in the action bar relevant to this screen
        // if the drawer is not showing. Otherwise, let the drawer
        // decide what to show in the action bar.
        getMenuInflater().inflate(R.menu.main, menu);
        restoreActionBar();
        return true;
    }
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((MainActivity) activity).onSectionAttached(
                getArguments().getInt(ARG_SECTION_NUMBER));
    }
}

}

Yanıtlar:


120

Burada gönderilen yanıtlar yardımcı olmadı, ancak aşağıdaki bağlantı işe yaramadı:

http://developer.android.com/training/basics/fragments/communicating.html

Arayüz Tanımlama

public class HeadlinesFragment extends ListFragment {
    OnHeadlineSelectedListener mCallback;

    // Container Activity must implement this interface
    public interface OnHeadlineSelectedListener {
        public void onArticleSelected(int position);
    }

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

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }

    ...
}

Örneğin, kullanıcı bir liste öğesini tıkladığında parçadaki aşağıdaki yöntem çağrılır. Parça, etkinliği üst etkinliğe iletmek için geri arama arabirimini kullanır.

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    // Send the event to the host activity
    mCallback.onArticleSelected(position);
}

Arayüzü Uygulama

Örneğin, aşağıdaki etkinlik yukarıdaki örnekten arabirimi uygular.

public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...

    public void onArticleSelected(int position) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article
    }
}

API 23 için güncelleme: 31.08.2015

Geçersiz kılınan yöntem onAttach(Activity activity)artık kullanımdan kaldırıldı android.app.Fragment, kodunonAttach(Context context)

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


@Override
public void onStart() {
    super.onStart();
    try {
        mListener = (OnFragmentInteractionListener) getActivity();
    } catch (ClassCastException e) {
        throw new ClassCastException(getActivity().toString()
                + " must implement OnFragmentInteractionListener");
    }
}

7
lütfen onAttach(Activity activity);kullanımdan kaldırıldığını ve bunun yerineonAttach(Context context)
EpicPandaForce

1
@EpicPandaForce Gerçekten haklısın, yazımı bunu yansıtacak şekilde güncelledim
meda

1
OnAttach'tan onStart'a geçmesinin bir nedeni var mı? hala etkinlik yerine bağlamı kullanarak ekleyebilir miyim?
Louis Tsai

Bence sadece kullanmak onAttach(context)iyi olur
EpicPandaForce

212

@Meda cevabını okuduktan sonra hala anlamayanlarınız için işte bu konuyla ilgili özlü ve tam açıklamam:

Diyelim ki 2 Fragmanınız var Fragment_Ave Fragment_Bbunlar uygulamadan otomatik olarak oluşturuldu. Oluşturduğunuz parçaların alt kısmında şu kodu bulacaksınız:

public class Fragment_A extends Fragment {

    //rest of the code is omitted

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

public class Fragment_B extends Fragment {

    //rest of the code is omitted

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

Sorunun üstesinden gelmek için, onFragmentInteractionetkinliğinize benim durumumda adlandırılan yöntem eklemeniz gerekiyor MainActivity2. Bundan sonra, bu şekilde implementstüm parçalara ihtiyacınız var MainActivity:

public class MainActivity2 extends ActionBarActivity
        implements Fragment_A.OnFragmentInteractionListener, 
                   Fragment_B.OnFragmentInteractionListener, 
                   NavigationDrawerFragment.NavigationDrawerCallbacks {
    //rest code is omitted

    @Override
    public void onFragmentInteraction(Uri uri){
        //you can leave it empty
    }
}

Not: Kısacası, bu yöntem parçalar arasında iletişim kurmak için kullanılabilir. Bu yöntem hakkında daha fazla bilgi edinmek isteyenler için lütfen bu bağlantıya bakın .


10
Android Studio'daki SDK'nın mevcut sürümünde , diğer yanıtların hiçbirinde belirtilmeyen yöntemi uygulamanızı gerektirironFragmentIntereactior(Uri) . +1

2
Çok teşekkür ederim!
ofir_aghai

Bundan bahsettiğiniz için teşekkürler. Bana çok yardım etti.
hablema

2
Gerektirir? Sadece dinleyicilerle ilgili kodu silebilirsiniz ... Diğer parçalarla etkileşime ihtiyaç duymayan parçalarınız varsa, bu dinleyiciler işe yaramaz.
iz

4
Takip etmek ve anlamak kabul edilen cevaptan çok daha kolay.
jerrythebum

44

FragmentAndroid Studio tarafından oluşturulan otomatik olarak oluşturulan öğelerinize bakın. FragmentYeniyi oluşturduğunuzda , Studio sizin için bir grup kod sapladı. Otomatik oluşturulan şablonun altında, adı verilen bir iç arabirim tanımı vardır OnFragmentInteractionListener. Kişisel Activityihtiyaçlar bu arabirim uygulamak. Bu, olaylarınızı Fragmentbildirmeniz için önerilen kalıptır, Activityböylece daha sonra başka bir tane yüklemek gibi uygun işlemi gerçekleştirebilir Fragment. Ayrıntılar için bu sayfaya bakın, "Etkinlik için olay geri aramaları oluşturma" bölümünü bulun : http://developer.android.com/guide/components/fragments.html


Belgelerde dinleyicinin parçada (zaten sihirbaz tarafından oluşturulmuş) nasıl uygulanacağını, ancak uygulamanın çökmesine neden olan ana etkinlikte nasıl gösterilmeyeceğini gösterir.
Mario M

3
Tam olarak değil. Doc (ve oluşturulan kod) arabirimi tanımlar Activityve Fragment. Gördüğünüz kilitlenme Activity, arabiriminizi uygulamamış olmanızdır . Aramanıza girmeniz Activityve implements YourFragment.OnFragmentInteractionListenerardından arabirimde tanımlanan yöntemin bir uygulamasını eklemeniz gerekir.
Larry Schiefer

Tamam, ama bu uygulamayı nasıl ekleyeceğimi bilmiyorum çünkü android sdk belgelerinde hiçbir yer yok
Mario M

1
SDK'nın bir parçası değil, en iyi uygulama. Sihirbaz tarafından üretilen şablon kodu sadece sizin için zemin hazırlıyor. Arayüz onFragmentInteraction(Uri uri)sadece bir saplama. Bu yöntemi istediğiniz her şeyi ve Activitybunu uygulamak için ihtiyaçlarınızı yapabilirsiniz. Bunun yardımcı olup olmadığını görün .
Larry Schiefer

3
Bu ipucu saatler sürdü. Parça oluştururken UN-check "parça fabrikası yöntemlerini ekle" ve "arayüz geri çağrılarını dahil et". Ve OnFragmentInteractionListener'ı uygulamak zorunda değilsiniz. Java sdk 8 ile Android studio 1.3.2 kullanıyorum. Android 6.0 (API 23) ve sdk-platform 23. Teşekkürler Larry Schiefer.
Öğrenci

28

Bu hatayla ilgili daha fazla açıklama arayan bu sayfayı ziyaret edenler için, benim durumumda, parçayı çağıran aktivitenin, bu durumda 2 uygulama olması gerekiyordu:

public class MyActivity extends Activity implements 
    MyFragment.OnFragmentInteractionListener, 
    NavigationDrawerFragment.NaviationDrawerCallbacks {
    ...// rest of the code
}

9

Aşağıdaki kodu parçalarınızdan kaldırmayı denemelisiniz

    try {
        mListener = (OnFragmentInteractionListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }

Arayüz / dinleyici, etkinliğinizin ve parçalarınızın daha kolay iletişim kurabilmesi için oluşturulmuş bir varsayılan değerdir


2
Bu dinleyicinin çoğu yeni uygulamada gerekli olmadığı için bu çok iyi bir nokta.
Code-Apprentice

5

@ User26409021 yanıtına ek olarak, bir ItemFragment eklediyseniz, ItemFragment içindeki mesaj;

Activities containing this fragment MUST implement the {@link OnListFragmentInteractionListener} interface.

Ve aktivitenize eklemelisiniz;

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener, ItemFragment.OnListFragmentInteractionListener {

//the code is omitted

 public void onListFragmentInteraction(DummyContent.DummyItem uri){
    //you can leave it empty
}

Burada kukla öğe, ItemFragment'inizin altında olan şeydir


5

Benimle çalıştı bu kodu silmek:

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

Şu şekilde bitiyor:

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

4

OnFragmentInteractionListeneretkinlik iletişim parçasını işlemek için varsayılan uygulama. Bu, ihtiyaçlarınıza göre uygulanabilir. Parçanızdaki belirli bir işlem sırasında yürütülecek bir işleve ihtiyacınız varsa, bu geri çağrı yöntemini kullanabileceğinizi varsayalım. Hosting activityile arasında bu etkileşime sahip olmanız gerekmiyorsa fragment, bu uygulamayı kaldırabilirsiniz.

Kısacası böyle bir implementparça-etkinlik etkileşimine ihtiyacınız varsa, dinleyici, parça barındırma etkinliğinizde olmalıdır

public class MainActivity extends Activity implements 
YourFragment.OnFragmentInteractionListener {..}

ve parçanızın şöyle tanımlaması gerekir

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

ayrıca void onFragmentInteraction(Uri uri);etkinliğiniz için tanım sağlar

ya da herhangi bir fragman-aktivite etkileşimi yoksa listenerbaşlatma işlemini fragmanınızdan kaldırınonAttach


3

Etkinlik yerine bağlam kullanın. Benim için çalışıyor.

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
}

3

Sadece bir zeyilname:

OnFragmentInteractionListener, bir arabirim (OnFragmentInteractionListener) kullanarak Etkinlik ve Parça arasındaki iletişimi yönetir ve Android Studio tarafından varsayılan olarak oluşturulur, ancak etkinliğinizle iletişim kurmanız gerekmiyorsa, sadece sürülebilir.

Amaç, parçanızı birden çok etkinliğe bağlayabilmeniz ve yine de aynı iletişim yaklaşımını yeniden kullanabilmenizdir (Her etkinliğin her bir parça için kendi OnFragmentInteractionListener'ı olabilir).

Ama ve eğer im parçam sadece bir tür faaliyete bağlı olacak eminim ve ben bu faaliyet ile iletişim kurmak istiyorum?

Ardından, ayrıntı düzeyi nedeniyle OnFragmentInteractionListener'ı kullanmak istemiyorsanız, etkinlik yöntemlerinize aşağıdakileri kullanarak erişebilirsiniz:

((MyActivityClass) getActivity()).someMethod()

Bu çoğu durumda işe yarar olsa da, getActivity () öğesi, çağrılırken parçalar etkinlikten ayrıldıysa, örneğin get asynctask'ın postExecute yönteminde, get aktivite çağırırsanız ancak zaten parçayı bıraktıysanız, bazen null döndürebilir. asyncTask tamamlanmadan önce bir boş gösterici istisnası alırsınız. Bu nedenle android belgeleri özellikle bir parça etkileşimi dinleyici arayüzü kullandığını söylüyor
MichaelStoddart

2

Sadece fragman Aktivite gidin ve createview yöntemi yerine tüm yöntemi ..... çıkarın.

parçanızın yalnızca görüntüleme üzerindeki yöntemde olduğu budur.

// sadece bu yöntem başka bir yöntem uygulamak silmek

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    return rootView;
}

ve düzeninizin u için demo olduğundan emin olun.


Eyvallah ... Bir şey gerekiyorsa kalpeshnikam1080@gmail.com posta bırakın
A.

1

Parça etkinlikten ayrıldığında veya yok edildiğinde dinleyicinin yok edilmesini eklemek istiyorum.

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

ve Context ile yeni onStart () yöntemini kullanırken

@Override
public void onDestroy() {
    super.onDestroy();
    mListener = null;
}
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.