프래그먼트에서 액티비티 메소드 호출


318

단편에서 내 활동의 메소드를 호출하려고합니다. 조각이 메서드 데이터를 제공하고 메서드가 반환 될 때 데이터를 가져 오기를 원합니다. 정적 메소드를 호출하는 것과 비슷하지만 정적을 사용하지 않고 활동에 문제가 발생하기를 원합니다.

조각이 처음이므로 쉽고 교육적인 설명이 필요합니다!

감사!

답변:


820

단편에서 활동으로 :

((YourActivityClassName)getActivity()).yourPublicMethod();

활동에서 단편으로 :

FragmentManager fm = getSupportFragmentManager();

//if you added fragment via layout xml
YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentById(R.id.your_fragment_id);
fragment.yourPublicMethod();

코드를 통해 프래그먼트를 추가하고 프래그먼트를 tag추가 할 때 문자열을 사용한 경우 findFragmentByTag대신 다음을 사용하십시오 .

YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentByTag("yourTag");

5
캐스트가 작동하지 않으면 예기치 않은 일이 발생하도록주의하십시오. : : S
Ewoks

48
캐스트 문제점을 피하려면 다음을 사용하십시오. Activity act = getActivity (); if (YourActivityClassName의 실제 인스턴스) ((YourActivityClassName) act) .yourPublicMethod (); }
ericharlow

@Richard : Activity 내에서 프래그먼트의 메소드를 수행해야한다면 어떻게 반대 행동을 수행 할 수 있습니까?
Himanshu

5
디자인이 잘못되어 활동을 전송하는 것이 안전하지 않습니다. 조각은 특정 활동으로 제한되지 않습니다.
Aviv Ben Shabat

3
@Kay 반드시 그런 것은 아닙니다. 조각은 더 큰 활동의 "조각"으로 사용될 수 있습니다. 예를 들어 반응 형 UI를 만들려면 나는 같은 조각을 거의 사용하지 않고 다른 활동 호스트에 첨부합니다.
Richard

201

다른 곳에서 사용하려는 경우 활동에서 프래그먼트를 분리하십시오. 활동이 구현하는 인터페이스를 작성하여이를 수행 할 수 있습니다.

따라서 다음과 같은 인터페이스를 정의합니다.

예를 들어 액티비티에 문자열을 제공하고 Integer를 리턴하도록한다고 가정하십시오.

public interface MyStringListener{
    public Integer computeSomething(String myString);
}

이것은 조각 또는 별도의 파일에서 정의 될 수 있습니다.

그런 다음 활동에 인터페이스를 구현하게하십시오.

public class MyActivity extends FragmentActivity implements MyStringListener{

  @Override
  public Integer computeSomething(String myString){
   /** Do something with the string and return your Integer instead of 0 **/ 
   return 0;
  }

}

그런 다음 조각에 MyStringListener 변수가 있고 조각 onAttach (Activity activity) 메서드에서 리스너를 설정합니다.

public class MyFragment {

        private MyStringListener listener;

        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            try {
                listener = (MyStringListener) context;
            } catch (ClassCastException castException) {
                /** The activity does not implement the listener. */
            }
        }

    }

편집 (2015 년 12 월 17 일) :onAttach(Activity activity) is deprecated, use onAttach(Context context) instead, it works as intended

첫 번째 대답은 확실히 작동하지만 현재 조각과 호스트 활동을 결합합니다. 다른 활동에서 조각을 사용하려는 경우 조각을 호스트 활동에서 분리하는 것이 좋습니다.


58
다른 사람이 이것을보고, 받아 들여진 대답은 분명히 작동하지만, 이것은 디자인 관점에서 더 좋고 더 안전한 접근법입니다.
Paul Richter

7
이 답변은 코드 디자인 측면에서 훨씬 낫습니다. 또한 활동이 잘못 캐스팅 된 경우 충돌이 발생하지 않습니다
David T.

3
+1이지만 onAttach에서 try-catch를 사용하지 않습니다. 실패하자. 리스너가 선택적인 경우 (즉, 실패가 적절하지 않은 경우) 조각에 set / addListener 메소드를 추가하십시오.
ataulm

반대쪽 통신은 developer.android.com/training/basics/fragments/… 를 참조하십시오 . 프래그먼트의 인터페이스 (위에서 설명한 것처럼 프래그먼트-> 액티비티 통신을 수행하는 안전한 방법이기도 함)를 사용하면 프래그먼트-> 액티비티를 기반으로 조치를 취하려는 경우 활동에서 프래그먼트에있는 메소드를 호출 할 수 있습니다 통신
Kerem

조각은 모든 활동에서 재사용 및 설정되어야합니다. 동일한 조각을 사용하는 5 가지 활동이있는 경우 어떻게합니까? Marco의 답은 조각 간 및 활동-조각 통신에 대한 정답이며 좋은 습관입니다.
blockwala

51

들어 코 틀린의 개발자

(activity as YourActivityClassName).methodName()

들어 자바 개발자

((YourActivityClassName) getActivity()).methodName();

이 코드를 실행하면 kotlin에 오류가 발생합니다. 다른 방법이 있습니까?
Jake Garbo

1
내가 그것을 실행할 때. ActivityClass의 null 값을 얻습니다.이 오류는 kotlin 에서이 작업을 수행하는 올바른 방법이 아니라고 생각합니다. 아니면 버그?
Jake Garbo

@JakeGarbo 그렇지 않으면 12 명이 투표에 참여하지 않은 올바른 방법입니다. 두 번째로 getActivity () 는 SO에서 해당 질문을 검사하여 null을 반환합니다.
Wasim K. Memon 5

@JakeGarbo Ya 그들은 당신에게 말했다. 그것이 당신을 위해 일했다면 그것을 이해하거나 다른 방법을 찾거나 먼저 코딩하는 법을 배우십시오.
Wasim K. Memon

13

조각이 어떻게 작동하는지 더 이해 한 후에 업데이트하십시오. 각 조각은 부모 활동에 속합니다. 따라서 다음을 사용하십시오.

getActivity().whatever

조각 내에서. superflous 캐스트를 피하기 때문에 더 나은 대답입니다. 이 솔루션으로 캐스트를 피할 수 없으면 아래의 캐스트를 사용하십시오.

============

당신이해야 할 일은 외부 활동에 캐스팅하는 것입니다

((MainActivity) getActivity()).Method();

새 인스턴스를 만들면 안드로이드 프레임이 혼란스러워 인식 할 수 없습니다. 또한보십시오 :

https://stackoverflow.com/a/12014834/1984636

https://stackoverflow.com/a/2042829/1984636


9

비록 Marco의 답변을 완전히 좋아하지만 게시 / 가입 기반 프레임 워크를 사용하여 동일한 결과를 얻을 수 있다고 지적하는 것이 공정하다고 생각합니다. 이벤트 버스를 사용하는 경우 다음을 수행 할 수 있습니다

조각 :

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

활동:

 @Subscribe
onSomeActionEventRecieved(DoSomeActionEvent doSomeActionEvent){
//Do something

}

5

kotlin에서는 다음과 같이 단편에서 활동 메소드를 호출 할 수 있습니다.

var mainActivity: MainActivity = activity as MainActivity
        mainActivity.showToast() //Calling show toast method of activity

2

프래그먼트를 통해 Activity에 선언 된 함수에 액세스하려면 marco의 답변에 표시된 인터페이스를 사용하십시오.

활동을 통해 Fragment에 선언 된 함수에 액세스하려면 태그 또는 ID가없는 경우 이것을 사용할 수 있습니다

private void setupViewPager(ViewPager viewPager) {
    //fragmentOne,fragmentTwo and fragmentThree are all global variables
    fragmentOne= new FragmentOne();
    fragmentTwo= new FragmentTwo();
    fragmentThree = new FragmentThree();

    viewPagerAdapteradapter = new ViewPagerAdapter(getSupportFragmentManager());
    viewPagerAdapteradapter.addFragment(fragmentOne, "Frag1");
    viewPagerAdapteradapter.addFragment(fragmentTwo, "Frag2");
    viewPagerAdapteradapter.addFragment(fragmentThree, "Frag3");

    //viewPager has to be instantiated when you create the activity:
    //ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
    //setupViewPager(viewPager);
    //Where R.id.pager is the id of the viewPager defined in your activity's xml page.

    viewPager.setAdapter(viewPagerAdapteradapter);


    //frag1 and frag2 are also global variables
    frag1 = (FragmentOne)viewPagerAdapteradapter.mFragmentList.get(0);
    frag2 = (FragmentTwo)viewPagerAdapteradapter.mFragmentList.get(1);;


    //You can use the variable fragmentOne or frag1 to access functions declared in FragmentOne


}

이것은 ViewpagerAdapterClass입니다

    class ViewPagerAdapter extends FragmentPagerAdapter {
    public final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

이 대답은 나와 같은 멍청한 사람들을위한 것입니다. 좋은 하루 되세요.


1

이것은 프래그먼트 클래스에서입니다 ...

((KidsStoryDashboard)getActivity()).values(title_txt,bannerImgUrl);

액티비티 클래스의이 코드 ...

 public void values(String title_txts, String bannerImgUrl) {
    if (!title_txts.isEmpty()) {

//Do something to set text 
    }
    imageLoader.displayImage(bannerImgUrl, htab_header_image, doption);
}

1

이 스레드에 표시된 모든 방법으로 시도했지만 아무도 효과가 없었습니다. 그것은 나를 위해 일했다.

((MainActivity) getContext().getApplicationContext()).Method();

0

호출하려는 모든 메소드가 동일한 Activity Parent가있는 Fragment에있는 것은 아니므로 최선의 방법을 찾고 있습니다.

당신의 조각에서

public void methodExemple(View view){

        // your code here

        Toast.makeText(view.getContext(), "Clicked clicked",Toast.LENGTH_LONG).show();
    }

당신의 활동에서

new ExempleFragment().methodExemple(context); 

0

((YourActivityName)getActivity()).functionName();

예 : ((SessionActivity)getActivity()).changeFragment();

참고 : 클래스 이름은 공개되어야합니다


0
((your_activity) getActivity).method_name()

your_activity활동 이름은 어디에 있고 method_name()호출하려는 메소드의 이름입니다.


0

Kotlin을 사용해보십시오.

class DataForm : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        Tasks(this).getData()
    }

    fun getResponse(response: String) {
        // code
    }
}

class Tasks(private val context: Any) {
    fun getData() {

        val getContext = (context as DataForm).activity
        val getFragment = (context as DataForm)

        val responseListener = Response.Listener<String> { response ->
            getFragment.getResponse(response)
        }

        val errorListener = Response.ErrorListener { error ->
            error.printStackTrace();
        }

        val stringRequest = StringRequest(Request.Method.GET, url, responseListener, errorListener)
        Volley.newRequestQueue(getContext).add(stringRequest)
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.