어댑터에서 활동 메소드 호출


119

Activityfrom에 정의 된 메서드를 호출 할 수 ListAdapter있습니까?

(난을 만들고 싶어 Button에서 list's행이 버튼을 클릭하면, 그것은 활동 대응에 정의 된 방법을 수행해야합니다. 나는 세트에 시도 onClickListener내에서 ListAdapter하지만 나는 그것의 경로 무엇이 메소드를 호출하는 방법을 모르겠어요. ..)

사용할 때 Activity.this.method()다음 오류가 발생합니다.

No enclosing instance of the type Activity is accessible in scope

어떤 아이디어?


해당 활동의 내부 클래스가 아닌 한 다른 클래스에서 activity.this를 호출 할 수 없습니다. 귀하의 경우에 @Eldhose M 바부 솔루션을 따라
Archie.bpgc

답변:


306

그래 넌 할수있어.

어댑터에서 새 필드 추가 :

private Context mContext;

어댑터 생성자에서 다음 코드를 추가하십시오.

public AdapterName(......, Context context) {
  //your code.
  this.mContext = context;
}

어댑터의 getView (...)에서 :

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
    if (mContext instanceof YourActivityName) {
      ((YourActivityName)mContext).yourDesiredMethod();
    }
  }
});

코드, 활동 등을 볼 수있는 자신의 클래스 이름으로 대체하십시오.

둘 이상의 활동에이 동일한 어댑터를 사용해야하는 경우 다음을 수행하십시오.

인터페이스 생성

public interface IMethodCaller {
    void yourDesiredMethod();
}

이 메소드 호출 기능이 필요한 활동에서이 인터페이스를 구현하십시오.

그런 다음 Adapter getView ()에서 다음과 같이 호출합니다.

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mContext instanceof IMethodCaller) {
            ((IMethodCaller) mContext).yourDesiredMethod();
        }
    }
});

완료되었습니다. 이 호출 메커니즘이 필요하지 않은 활동에이 어댑터를 사용해야하는 경우 코드가 실행되지 않습니다 (확인에 실패한 경우).


29
이것은 인기있는 질문이므로이 솔루션을 사용하지 않는 것이 좋습니다. 런타임 예외가 발생할 수 있으므로 여기서 클래스 캐스팅을 피해야합니다.
Igor Filippov 2014

3
Eldhose bro, 나는 당신에게 반대하는 것이 없지만 아래 대답은 모범 사례입니다. 댓글을 읽을 수도 있습니다. 코드 재사용을 피할 수 있으므로 mContext를 Activity에 캐스팅해서는 안됩니다. 이제이 어댑터는 mContext 변수를 캐스트 한 활동 내에서만 사용할 수 있습니다. 여기서 리스너가 정의되어 있으면 다른 활동에서 동일한 어댑터를 재사용 할 수 있습니다. 저는 업계에서 충분한 시간을 보냈으며 여기서 당신을 도우려고 노력하고 있습니다. 개인적으로 받아들이지 마십시오.
Varundroid

2
이 솔루션은 내가 지금까지 찾은 것 중 최고 중 하나입니다. 바부 씨 감사합니다. 이렇게 활동의 메서드를 호출하면 전체 앱에 500 %의 성능 향상이 제공됩니다.-> 액세스해야하는 어댑터에서 데이터베이스를 다시로드 할 필요가 없습니다. 나는 "업계에서의 년"에 대해 신경 쓰지 않고 안정적이고 작동하는 솔루션을 찾고 있으며 액세스를 얻는 더 좋은 방법을 찾지 못할 것이라고 확신합니다. DB를 싱글 톤으로 설정할 수는 있지만 이것이 내 프로젝트를 "구조화 해제"하려는 방식이 아닙니다.
마틴 페퍼

2
@RAM 둘 이상의 활동에서 동일한 메서드를 호출해야하는 경우 해당 메서드 이름으로 인터페이스를 만들어야합니다. 그런 다음 메서드 호출을 사용하는 데 필요한 모든 활동에서 해당 인터페이스를 구현합니다. 그런 다음 클릭 리스너에서 활동 이름을 사용하는 대신 인터페이스의 인스턴스를 확인하십시오.
Eldhose M 바부

1
훌륭한 대답입니다. 엄지 손가락
알록 Rajasukumaran

126

다음과 같이 할 수 있습니다.

인터페이스 선언 :

public interface MyInterface{
    public void foo();
}

당신의 활동이 그것을 구현하게하십시오 :

public class MyActivity extends Activity implements MyInterface{
    public void foo(){
        //do stuff
    }
}

그런 다음 활동을 ListAdater에 전달합니다.

public MyAdapter extends BaseAdater{
    private MyInterface listener;

    public MyAdapter(MyInterface listener){
        this.listener = listener;
    }
}

그리고 어댑터 어딘가에서 해당 Activity 메서드를 호출해야 할 때 :

listener.foo();

5
처음에는 위의 방법을 조각으로 생각했지만 이것이 최선의 해결책입니다!
brux 2013-08-02

1
내 InterfaceListener입니까? 어떻게 초기화 할 수 있습니까? public MyAdapter (MyInterface listener) {this.listener = listener; }
Gilberto Ibarra 2014

6
(활동에서) 어댑터에 인터페이스를 어떻게 전달합니까?
Brandon

1
@Brandon은 어댑터의 생성자 매개 변수로 전달할 수 있습니다.
이고르 필리포

5
@Brandon, 어댑터에 인터페이스를 전달하려면 'this'를 추가하십시오. myAdapter = new MyAdapter (this);
ajinkya

67

실물:

나는 현재 답변을 이해하지만 더 명확한 예가 필요했습니다. 다음은 Adapter(RecyclerView.Adapter) 및 Activity.

활동에서 :

이것은 interface우리가 가지고있는 Adapter. 이 예에서는 사용자가 .NET Framework의 항목을 클릭 할 때 호출됩니다 RecyclerView.

public class MyActivity extends Activity implements AdapterCallback {

    private MyAdapter myAdapter;

    @Override
    public void onMethodCallback() {
       // do something
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myAdapter = new MyAdapter(this);
    }
}

어댑터에서 :

에서 Activity, 우리는 우리를 시작 Adapter하고 constructer에 인수로이를 통과시켰다. 이것은 interface콜백 메소드를 시작합니다 . 사용자 클릭에 콜백 메서드를 사용하는 것을 볼 수 있습니다.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private AdapterCallback adapterCallback;

    public MyAdapter(Context context) {
        try {
            adapterCallback = ((AdapterCallback) context);
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement AdapterCallback.", e);
        }
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int position) {
        // simple example, call interface here
        // not complete
        viewHolder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    adapterCallback.onMethodCallback();
                } catch (ClassCastException e) {
                   // do something
                }
            }
        });
    }

    public static interface AdapterCallback {
        void onMethodCallback();
    }
}

6
감사합니다. 정확히 제가 찾던 것입니다. 최대 - 투표
Nactus

이것은 나를 위해 일했습니다! imo, 지금까지 가장 완벽한 작업 코드!
publicknowledge

2
이 솔루션을 주셔서 감사합니다
스티브

4
이 답변은 더 많은 찬성표를 가져야합니다. 깨끗하고 완벽한 솔루션입니다.
Opiatefuchs

안녕하세요 @Jared- EventBus제안한 것과 동일한 샘플을 맞출 수 있습니까 ?
Tohid

15

기본적이고 간단합니다.

어댑터에서 이것을 사용하십시오.

((YourParentClass) context).functionToRun();


4
클래스 대신 YourParentClass 유형으로 만 작동하도록 클래스를 제한하고 있기 때문에 좋은 습관은 아니지만, 재사용에 신경 쓰지 않으면 작동합니다. 클래스 이름도 변경하면 코드가 깨집니다 ...
Gustavo Baiocchi Costa

7

또 다른 방법은 다음과 같습니다.

어댑터에 메소드를 작성하면 public void callBack () {}을 말할 수 있습니다.

이제 활동중인 어댑터에 대한 개체를 만드는 동안이 메서드를 재정의합니다. 어댑터에서 메서드를 호출하면 Override 메서드가 호출됩니다.

Myadapter adapter = new Myadapter() {
  @Override
  public void callBack() {
    // dosomething
  }
};

5

Kotlin의 경우 :

어댑터에서 간단히

(context as Your_Activity_Name).yourMethod()

0
if (parent.getContext() instanceof yourActivity) {
  //execute code
}

이 조건은 귀하 GroupViewgetView()메소드 에서 요청하는 뷰 를 가진 활동 adapteryourActivity

참고 : parent그 GroupView입니다


이 GroupView는이 호출 어댑터에서보기 요청 getView()우리가 GroupView 그 컨텍스트를 얻고, 위의 조건을 통해 검사 있도록 ..... 방법을
압드 살람 베이커

0

Kotlin에는 인터페이스가 필요없는 람다 함수를 사용하는 더 깨끗한 방법이 있습니다.

class MyAdapter(val adapterOnClick: (Any) -> Unit) {
    fun setItem(item: Any) {
        myButton.setOnClickListener { adapterOnClick(item) }
    }
}

class MyActivity {
    override fun onCreate(savedInstanceState: Bundle?) {
        var myAdapter = MyAdapter { item -> doOnClick(item) }
    }


    fun doOnClick(item: Any) {

    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.