I have RecyclerView with very complex item, multiple buttons/images/texts. To access each button/image I set my click Listeners inside my Adapter class.
But now I am trying add function to set contact ringtone and I have a problem.
I am calling the onActivityResult method like this:
Intent contactIntent = new Intent(Intent.ACTION_PICK); contactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE); contactIntent.putExtra("RINGTONE_POSITION", position); ((Activity) context).startActivityForResult(contactIntent, CONTACT_CHOOSER_ACTIVITY_CODE );
and that works fine. But here is the problem:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { .... ... ... } }
I get this error: Cannot resolve method 'onActivityResult(int, int, android.content.Intent)'
Is there any way to avoid this? or is it possible to have this method inside adapter class? If not what should I do?
You cannot have this in any Adapter class, this is only a method inside Activity
, each class that extends Activity
will be able to Override this method but certainly not an Adapter.
Please see Overrides in java
And for onActivityResult
please see Activity#onActivityResult(int, int, Intent)
For something like a RecyclerView.Adapter
you are going to want to define an interface in your adapter and implement that interface in your Activity.
For example here is code for an application that sends a String of the Item clicked and its position to a new Activity which displays it:
MainActivity:
public class MainActivity extends AppCompatActivity implements MyAdapter.CallbackInterface { private static final int MY_REQUEST = 1001; private static final String [] ITEMS = {"Item 1", "Item 2", "Item 3" ,"Item 4", "Item 5", "Item 6"}; private MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ... Adapter setup, simple LinearLayoutManager and String [] used RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rec_view); myAdapter = new MyAdapter(this, ITEMS); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(myAdapter); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(resultCode){ case RESULT_OK: // ... Check for some data from the intent if(requestCode == MY_REQUEST){ // .. lets toast again int position = -1; if(data != null){ position = data.getIntExtra("Position", 0); } if(position != -1) { Toast.makeText(this, "Handled the result successfully at position " + position, Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(this, "Failed to get data from intent" , Toast.LENGTH_SHORT).show(); } } break; case RESULT_CANCELED: // ... Handle this situation break; } } /** * Interface Method which communicates to the Acitivty here from the {@link MyAdapter} * @param position - the position * @param text - the text to pass back */ @Override public void onHandleSelection(int position, String text) { Toast.makeText(this, "Selected item in list "+ position + " with text "+ text, Toast.LENGTH_SHORT).show(); // ... Start a new Activity here and pass the values Intent secondActivity = new Intent(MainActivity.this, DetailActivity.class); secondActivity.putExtra("Text",text); secondActivity.putExtra("Position", position); startActivityForResult(secondActivity, MY_REQUEST); } }
xml for MainActivity:
MyAdapter:
public class MyAdapter extends RecyclerView.Adapter{ private CallbackInterface mCallback; private String [] mMyItems; private Context mContext; public interface CallbackInterface{ /** * Callback invoked when clicked * @param position - the position * @param text - the text to pass back */ void onHandleSelection(int position, String text); } public MyAdapter(Context context, String [] myItems){ mContext = context; mMyItems = myItems; // .. Attach the interface try{ mCallback = (CallbackInterface) context; }catch(ClassCastException ex){ //.. should log the error or throw and exception Log.e("MyAdapter","Must implement the CallbackInterface in the Activity", ex); } } @Override public int getItemCount() { return mMyItems.length; } @Override public long getItemId(int position) { return position; } @Override public void onBindViewHolder(MyHolder holder, final int position) { // Set the text for the View holder.mTextView.setText(mMyItems[position]); // Use your listener to pass back the data holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mCallback != null){ mCallback.onHandleSelection(position, mMyItems[position]); } } }); } @Override public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false); return new MyHolder(view); } static class MyHolder extends RecyclerView.ViewHolder{ TextView mTextView; public MyHolder(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(R.id.tv_list_item); } } }
layout for the Adapter:
and the DetailActivity:
public class DetailActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.detail_activity); TextView textView = (TextView) findViewById(R.id.tv_detail_text); if(getIntent() != null && getIntent().getExtras() != null) { Bundle extras = getIntent().getExtras(); String text = extras.getString("Text"); int position = extras.getInt("Position"); textView.setText(String.format("%s at position %d", text, position)); // .. For this purpose set result okay and use position as part of data when Activity finishes // Which will in turn invoke the onActivityResult method in the calling activity Intent resultIntent = new Intent(); resultIntent.putExtra("Position", position); setResult(RESULT_OK, resultIntent); } } }
layout for Detail activity:
Good luck and happy coding!
Another solution is to set onActivityResult method in activity class where you initiate your RecyclerView/ListView. That works too, except for some reason I got NPE errors when I tried to pass data using intents, so work-arround for that is create static String/Int and change it's value on clicks and access. That works just fine. But the answer above is also great, and it works just as fine, perhaps even better, performance wise.