본문 바로가기

MOBILE/android

[Android] common Intent: android에서 웹을 검색어로 연결하자 근데 여기에 RecyclerView를 곁들인.

android에서 웹을 열고 싶은데 검색어를 검색한 웹을 열고 싶을 때는 common intent를 쓰면 된다

 

구글 공식 문서에 공통 인텐트에 대한 내용이 상세하게 나와있다.

https://developer.android.com/guide/components/intents-common?hl=ko#java 

 

Intent의 action을 ACTION_WEB_SEARCH

SearchManager.QUERY를 intent의 extra로 넣으면 된다.

구글 공식 문서에 잘 설명해둠

 

 

 

이걸 나의 프로젝트에 적용해보면

일단 recycler view의 item을 클릭했을 때 textView의 text를 가져와서 web으로 검색하는 코드이다.

그럼 쉽게

 

TextView query=v.findViewById(R.id.textTitle);
Intent intent=new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,query.getText().toString());
startActivity(intent);

 

이렇게 쓰면 되겠지요?

근데 나는 여기서 끝낼 수 없음...왜냐면 recycler view의 item이기 때문이다.

 


RecyclerView에서 click event 처리하기

recycler view의 item에 click listener를 등록하려면 먼저 recycler view의 특징을 알아야한다.

recycler view는 레이아웃매니저(LayoutManager)를 통해 아이템을 배치하는 형태를 list보다 다양하게 구성 가능하다.

예를 들면 가로로 2개씩 3개씩 등등 자유롭게~~

 

근데 이렇게 복잡하기 때문에 view자체에서 click 이벤트를 처리하지 않고, click listener를 아이템 뷰에 등록해서 처리해야한다.

그게 바로 ViewHolder class에서 이루어진다.

 

// adapter안에 정의된 RecyclerView.ViewHolder를 상속받는 내부 클래스
class test extends RecyclerView.ViewHolder{
  public test(@NonNull View itemView) {
      super(itemView);

      // itemview에서 click event를 처리해야한다.
      itemView.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {
             // click event 처리 여기서 함
          }
      });
}

 

왜냐면 이 recycler view의 adapter로 itemview를 만들면 ViewHolder 객체에 저장되고 그게 표시되는 것이기 때문

따라서 itemView가 ViewHolder 객체에 저장되어 있으니 여기서 만들어주면 된다.

ViewHolder 클래스를 상속받는 클래스의 생성자에서 등록해주면 만들어질때 같이 등록되니 좋다

어쨌든 click event를 이렇게 처리할 수 있는데 activity의 상속이 필요하다면?

-> 커스텀 리스너 인터페이스를 생성해서 그걸 MainActivity에서 받아서 리스너의 click을 정의하면 된다.

 

 

custom listener interface

1. 커스텀 리스너 인터페이스를 정의한다. 이때 추상메서드로 onItemClick을 써둔다.

    -> 이게 나중에 MainActivity에서 받아 구현해서 click event를 처리하게 된다

2.  이 리스너 객체를 전달하는 메서드를 정의한다. 그리고 이걸 저장할 리스너 변수도 만들어서 파라미터로 받은거를 저장해둔다.

 

// 리스너 저장 변수
private static onAstroClickListener astroClickListener=null;

// 1번
public interface onAstroClickListener{
    void onItemClick(View v);
}

// 2번
public void setOnAstroClickListener(onAstroClickListener listener){
    this.astroClickListener=listener;
}

 

 

3. clickevent 처리하는 리스너의 onClick에 커스텀 리스너의 click listener를 연결해준다.

 

itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if(astroClickListener!=null){
            astroClickListener.onItemClick(view);
        }
    }
});

 

 

4. MainActivity에서 받아서 정의해서 쓰면 됨

 

adapter.setOnAstroClickListener(new AstroAdapter.onAstroClickListener() {
    @Override
    public void onItemClick(View v) {
    	// 여기서 처리하면 됨
    }
});

 

 

그래서 결국 흐름이 어떻게 이어지냐면

시작 => recyclerview에서 item이 click됨

=> viewholder 생성자에서 itemview에 등록되었던 setOnClickListener 가 호출됨

=> 리스너 안의 onClick 메서드에서 커스텀 인터페이스의 onItemClick가 호출됨

=> 근데 이 인터페이스의 정의는 MainActivity에 되어있음

=> MainActivity에서 인터페이스의 onItemClick를 호출

 

그래서 내 프로젝트의 코드는 다음과 같다.

 

adapter=new AstroAdapter(items,this);
// 메인 액티비티에서 커스텀 리스너 객체 생성해서 처리
adapter.setOnAstroClickListener(new AstroAdapter.onAstroClickListener() {
    @Override
    public void onItemClick(View v) {
        TextView query=v.findViewById(R.id.textTitle);
        Intent intent=new Intent(Intent.ACTION_WEB_SEARCH);
        intent.putExtra(SearchManager.QUERY,query.getText().toString());
        startActivity(intent);
    }
});
recyclerView.setAdapter(adapter);

 

startActivity를 할려면 이 귀찮은 짓을 해야한다................