Как я могу реализовать onActivityResult внутри адаптера?

Может кто-нибудь объяснить мне с помощью некоторых фрагментов кода, как мы можем восстановить результат onActivityResult внутри Адаптера? Я читал некоторые об интерфейсах, но я не мог попытаться реализовать это. Спасибо заранее!

Пример: внутри адаптера у меня есть ViewHolder, внутри которого происходит событие ImageView.An, щелкнув по этому ImageView, запускает startActivityForResult. Но в том же адаптере мне нужно восстановить результат onActivityResult метод.

Как сделать со следующим:

Основная деятельность:

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 );

    }
}

адаптер:

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();
            }

        }
    }
}

2 ответа

Вы можете определить интерфейс...

public interface OnIntentReceived {
  void onIntent(Intent i, int resultCode);
}

Реализуйте интерфейс на адаптере. Примечание: вам нужен только контекст в адаптере, а не экземпляр действия

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);

}

В упражнении определите адаптер и перенаправьте результат намерения в интерфейс обратного вызова.

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);
        }
    }
  }
}

Ответ @cricket_007 правильный, но есть и другой способ - использовать Observable а также Observer архитектура,

Observer в вашем случае это адаптер, а Observable это объект, который будет содержать данные, полученные из onActivityResult через вашу деятельность: 1- Создайте наблюдаемое:

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- Добавьте его в класс Observer (адаптер)

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- Позвоните Наблюдателю из вашей деятельности. Результат:

@Override
public void oActivityResult( ... ) {
    MyObserver.getInstance().sendData(yourData);
}