Как я могу реализовать 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);
}