Reputation:
Can someone explain me, with some code snippets, how we can recover the result of onActivityResult inside an Adapter? I've read some about interfaces, but i couldn't be able trying implementing this.Thanks in advance!
Example:
Inside the adapter i have a ViewHolder, inside which is an ImageView.An event clicking on this ImageView starts an startActivityForResult
.But in the same adapter i need to recover the result by onActivityResult
method.
How to do with the following:
MainActivity:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<Filme> listaFilmes = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
//Listagem de filmes
this.criarFilmes();
//Configurar adapter
final Adapter adapter = new Adapter(listaFilmes,getApplicationContext(),MainActivity.this);
//Configurar Recyclerview
//Para mostrar na horizontal: new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.HORIZONTAL,false);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.HORIZONTAL,false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration( new DividerItemDecoration(this, LinearLayout.VERTICAL));
recyclerView.setAdapter(adapter);
}
public void criarFilmes(){
Filme filme = new Filme("Homem Aranha - De volta ao lar","Aventura","2017");
this.listaFilmes.add( filme );
}
}
Adapter:
public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
private List<Filme> listaFilmes;
private Context context;
private Activity activity;
private ImageView imagem;
private Uri photoURI;
Uri filePath;
String mCurrentPhotoPath;
static final int REQUEST_TAKE_PHOTO = 1;
public Adapter(List<Filme> listaFilmes, Context context,Activity activity) {
this.listaFilmes = listaFilmes;
this.context = context;
this.activity = activity;
}
//Aqui ele cria apenas a visualização
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLista = LayoutInflater.from(parent.getContext())
.inflate(R.layout.adapter_lista, parent, false);
return new MyViewHolder(itemLista);
}
//A exibição dos itens ocorre aqui
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
final Filme filme = listaFilmes.get(position);
/*holder.titulo.setText(filme.getTituloFilme());
holder.genero.setText(filme.getGenero());
holder.ano.setText(filme.getAno());*/
holder.imagem.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
Toast.makeText(context, "imagem removida", Toast.LENGTH_SHORT).show();
listaFilmes.remove(position);
notifyDataSetChanged();
return false;
}
});
holder.imagem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context, "imagem clicada", Toast.LENGTH_SHORT).show();
listaFilmes.add(position+1,filme);
notifyDataSetChanged();
selectImage();
}
});
}
//Retorna a quantidade de itens que serão exibidos
@Override
public int getItemCount() {
return listaFilmes.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
/*TextView titulo;
TextView ano;
TextView genero;*/
ImageView imagem;
public MyViewHolder(View itemView) {
super(itemView);
imagem = itemView.findViewById(R.id.image_id);
/*titulo = itemView.findViewById(R.id.textTitulo);
ano = itemView.findViewById(R.id.textAno);
genero = itemView.findViewById(R.id.textGenero);*/
}
}
/*Função seleciona foto da galeria ou tira foto*/
public void selectImage() {
final CharSequence[] options = { "Take Photo", "Choose from Gallery","Cancel" };
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Add Photo!");
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (options[item].equals("Take Photo"))
{
dispatchTakePictureIntent(activity);
}
else if (options[item].equals("Choose from Gallery"))
{
Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
((Activity) context).startActivityForResult(intent, 2);
}
else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
//ativa a camera para tirar foto
public void dispatchTakePictureIntent(Activity currentActivity) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//Ensure that there`s a camera activity to handle the intent
if(takePictureIntent.resolveActivity( context.getApplicationContext().getPackageManager() ) != null ){ //getActivity
//Create the File where the photo should go
File photoFile = null;
try{
photoFile = createImageFile(currentActivity);
}catch(IOException ex){
//Error occurred while creating the File
ex.printStackTrace();
}
//Continue only if the File was successfully created
if(photoFile != null){
Log.i("ENTFR11","photofile:"+ photoFile); // /storage/emulated/0/Android/data/com.droidelivery.droidelivery/files/Pictures/JPEG_20171010_205010_1588304974.jpg
photoURI = FileProvider.getUriForFile(context.getApplicationContext(), //getActivity
"com.example.lucas.recyclerview.fileprovider",
photoFile);
Log.i("ENTFR12","photofURI:"+ photoURI); // content://com.example.android.fileprovider/my_images/JPEG_20171010_205010_1588304974.jpg
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); //ESTUDAR ESSA LINHA ESTÄ COM PROBLEMA.COMO RECUPERAR EXTRA_OUTPUT
Log.i("ENTFR13","photoURI: " + photoURI);
((Activity) context).startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
//Create a collision-resistant file name
public File createImageFile(Activity currentActivity) throws IOException {
//Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault() ).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = currentActivity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /*prefix*/
".jpg", /*suffix*/
storageDir /*directory*/
);
//Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
public void setPic() {
// Get the dimensions of the View
int targetW = imagem.getWidth();
int targetH = imagem.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
imagem.setImageBitmap(bitmap);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK ) { //lembrar que activity que requisita foto nao retorna necessariamente uma URI!!!
//filePath = data.getData();
//filePath = photoURI;
setPic();
}
if(requestCode == 2 && resultCode == RESULT_OK && data != null){
Toast.makeText(context, "requestCode == 2", Toast.LENGTH_SHORT).show();
try {
//getting image from gallery
Uri selectedImage = data.getData();
Log.i("SSS","selectedImage: " + selectedImage);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), selectedImage);//getContext
imagem.setImageBitmap(bitmap);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
Upvotes: 1
Views: 7199
Reputation: 191681
You could define an interface...
public interface OnIntentReceived {
void onIntent(Intent i, int resultCode);
}
Implement interface on the adapter. Note: You only need a Context in an adapter, not also an Activity instance
public class MyAdapter extends RecyclerView.Adapter<T> implements OnIntentReceived {
private Context mContext;
@Override public void onIntent(Intent i, int resultCode) {
// TODO: Handle here
}
// Somewhere in here, mContext.startActivityForResult(MyActivity.REQUEST_CODE);
}
In the activity, define the adapter and forward the intent result to the callback interface
public class MyActivity extends AppCompatActivity {
public static final int REQUEST_CODE = 101;
private MyAdapter mAdapter;
private List data = new ArrayList();
private OnIntentReceived mIntentListener;
@Override protected void onCreate(Bundle b) {
...
mAdapter = new MyAdapter(this, data);
mIntentListener = mAdapter;
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (mIntentListener != null) {
mIntentListener.onIntent(data, resultCode);
}
}
}
}
Upvotes: 3
Reputation: 3313
The answer of @cricket_007 is correct, but there is another way is to use Observable
and Observer
architecture,
The Observer
in your case is the Adapter, while the Observable
is the object that will hold the data retrieved from the onActivityResult
through your activity:
1- Create the Observable:
public class MyObservable extends Observable {
private static MyObservable instance = null;
private MyObservable() {
}
public static MyObservable getInstance() {
if(instance == null) {
instance = new MyObservable() ;
}
return instance;
}
public void sendData(Object data) {
setChanged();
notifyObservers(data);
}
}
2- Add it to the Observer class (the adapter)
public class MyAdapter extends BaseAdapter implements Observer {
// add the observer to the observable through:
MyObservable.getInstance().addObserver(this);
...
@Override
public void update(Observable observable, Object o) {
if(observable instanceof MyObservable) {
// do what you need here
}
}
3- Call the Observer from your activityResult:
@Override
public void oActivityResult( ... ) {
MyObserver.getInstance().sendData(yourData);
}
Upvotes: 1