I'm working on an app in the Android studio. Click the button in the Fragment to open a dialog box and include a picture and a brief description. (Pictures are taken from your gallery.) Click OK to close the dialog box and include the image and description in the RecyclerView that exists in the Fragment. But this code that I've woven has a description, but it doesn's image. I wanted to hear a solution to this, so I asked you a question.
I'd appreciate your reply!
To briefly explain how my code works, when I receive an image from the dialog box, I send the path (/storage/emulated/0/Pictures/a.jpg) of the file as a toast message, and as soon as the dialog is closed, the imagepath and description are transferred to the String form, and the imagepath is converted from Fragment to uri and changed to Bitmap using it to apply to RecyclerView.
Below is my code.
Fragment.java
btn_addlist = view.findViewById(R.id.btn_addlist);
btn_addlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment_cus dialog = new DialogFragment_cus();
dialog.show(getActivity().getSupportFragmentManager(), "tag");
dialog.setDialogResult(new DialogFragment_cus.OnMyDialogResult() {
// result : uri, result2 : dlg_edtName, result3 : dlg_edtSubtitle
#Override
public void finish(String result, String result2, String result3) {
imageUri = result; RecyclerInputName = result2;
RecyclerInputSubtitle = result3;
Uri uri = Uri.parse("file://" + imageUri);
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
RecyclerItem_cus item = new RecyclerItem_cus(bitmap, RecyclerInputName, RecyclerInputSubtitle);
mArrayList.add(0, item);
mAdapter.notifyDataSetChanged();
Toast.makeText(getActivity(), "finish.", Toast.LENGTH_SHORT).show();
}
});
}
});
DialogFragment.java
dlg_AddButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_PICK);
startActivityForResult(intent, 1);
}
});
dlg_ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment_cus fragment = new DialogFragment_cus();
String input1 = dlg_edtName.getText().toString();
String input2 = dlg_edtSubtitle.getText().toString();
if(fragment != null) {
if(mDialogResult != null ) {
mDialogResult.finish(name_Str, input1, input2);
}
}
dismiss();
}
});
dlg_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
return view;
}
public void setDialogResult(OnMyDialogResult dialogResult){
mDialogResult = dialogResult;
}
public interface OnMyDialogResult{
void finish(String result, String result2, String result3);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1 && resultCode == RESULT_OK) {
try {
name_Str = getImageNameToUri(data.getData());
InputStream in = getActivity().getContentResolver().openInputStream(data.getData());
Bitmap img = BitmapFactory.decodeStream(in);
in.close();
dlg_ImageView.setImageBitmap(img);
dlg_ImageView.setBackgroundResource(android.R.color.white);
Toast.makeText(getActivity(), "name_Str : "+name_Str , Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String getImageNameToUri(Uri uri) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, null);
getActivity().startManagingCursor(cursor);
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(columnIndex);
}
RecyclerView_cusAdapter.java
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, int i) {
final RecyclerItem_cus item = items.get(i);
if (item != null) {
Glide.with(context)
.load(item.getImage())
.asBitmap()
.format(DecodeFormat.PREFER_ARGB_8888)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
myViewHolder.cus_img.setImageBitmap(resource);
}
});
myViewHolder.cus_title.setText(item.getTitle());
myViewHolder.cus_subtitle.setText(item.getSubTitle());
}
}
#Override
public int getItemCount() {
return this.items.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView cus_title;
TextView cus_subtitle;
ImageView cus_img;
public MyViewHolder(View itemView) {
super(itemView);
cus_title = itemView.findViewById(R.id.cus_title);
cus_subtitle = itemView.findViewById(R.id.cus_subtitle);
cus_img = itemView.findViewById(R.id.cus_img);
}
}
RecyclerItem_cus.java
public class RecyclerItem_cus {
private Bitmap image;
private String title;
private String subTitle;
public RecyclerItem_cus(Bitmap image, String title, String subTitle) {
this.image = image;
this.title = title;
this.subTitle = subTitle;
}
public Bitmap getImage() {
return image;
}
public String getTitle() {
return title;
}
public String getSubTitle() {
return subTitle;
}
You can try to use Glide with the File object directly :
Glide.with(mContext)
.load(new File(item.getImage())) // Uri of the picture
.into(myViewHolder.cus_img);
Related
I have a homework about doing whatsapp clone. But I have a problem. I have a add contact screen. Users choose an image from gallery and enter their name. When they click add button, list item will be added to chat activity. Screenshot is below. I have a person class like:
public class Person
{
private int id;
private string name;
private int imageId;
public Person(int id, string name, int imageId)
{
this.id = id;
this.name = name;
this.imageId = imageId;
}
public int Id // property
{
get { return id; } // get method
set { id = value; } // set method
}
public string Name // property
{
get { return name; } // get method
set { name = value; } // set method
}
public int ImageId // property
{
get { return imageId; } // get method
set { imageId = value; } // set method
}
public static explicit operator Java.Lang.Object(Person v)
{
throw new NotImplementedException();
}
}
public class PersonAdapter : BaseAdapter
{
private LayoutInflater mInflater;
private List<Person> personArrayList;
public PersonAdapter(Activity activity, List<Person> personArrayList)
{
this.mInflater = (LayoutInflater)activity.GetSystemService(Context.LayoutInflaterService);
this.personArrayList = personArrayList;
}
public override int Count => personArrayList.Count;
public override Object GetItem(int position)
{
return (Object)personArrayList.ElementAt(position);
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
convertView = mInflater.Inflate(Resource.Layout.List_Item, null);
TextView personName = (TextView)convertView.FindViewById(Resource.Id.name);
TextView personMessage = (TextView)convertView.FindViewById(Resource.Id.message);
ImageView personImage = (ImageView)convertView.FindViewById(Resource.Id.imageView);
Person person = personArrayList.ElementAt(position);
personName.Text = person.Name;
if(MainActivity.messages[person.Id].Count != 0)
{
personMessage.Text = MainActivity.messages[person.Id][MainActivity.messages[person.Id].Count - 1];
}
else
{
personMessage.Text = "";
}
personImage.SetImageResource(person.ImageId);
return convertView;
}
}
}
I have a personAdapter class and chat activity has only listView. So I am binding list to listView via adapter. I added some person manually to see chat menu. If I add images to drawable folder, there is no problem. But how do I add images to create new person. I can't add images to drawable at runtime. When I try to read images from external storage. They have no resource id. So person class do not accept that.
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
public static List<Person> persons = new List<Person>();
public static Dictionary<int, List<string>> messages = new Dictionary<int, List<string>>();
PersonAdapter adapter;
private static int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
persons.Add(new Person(0,"Safa", Resource.Drawable.person));
persons.Add(new Person(1,"Melis", Resource.Drawable.person));
persons.Add(new Person(2,"Orkun", Resource.Drawable.person));
messages[0] = new List<string>();
messages[1] = new List<string>();
messages[2] = new List<string>();
messages[0].Add("Naber?");
messages[0].Add("Nasılsın?");
messages[1].Add("Nerdesin?");
messages[1].Add("Saat Kaç?");
messages[2].Add("Buluşalım mı?");
messages[2].Add("Kaçta?");
ListView listView = (ListView)FindViewById(Resource.Id.listView);
adapter = new PersonAdapter(this,persons);
listView.Adapter = adapter;
listView.ItemClick += (object sender, ItemClickEventArgs e) =>
{
Person person = persons[e.Position];
var intent = new Intent(this, typeof(ChatActivity));
intent.PutExtra("name", person.Name);
intent.PutExtra("id", person.Id);
this.StartActivity(intent);
};
FloatingActionButton fab = (FloatingActionButton)FindViewById(Resource.Id.fab);
fab.Click += delegate
{
var intent = new Intent(this, typeof(AddContactActivity));
this.StartActivity(intent);
};
if(Intent.GetStringExtra("person") != null)
{
Person newPerson = JsonConvert.DeserializeObject<Person> (Intent.GetStringExtra("person"));
persons.Add(newPerson);
messages.Add(newPerson.Id, new List<string>());
adapter.NotifyDataSetChanged();
}
}
}
}
AddContactActivity:
public class AddContactActivity : Activity
{
private ImageView imageView;
private Button loadButton;
private Button addButton;
private EditText nameEditText, surnameEditText;
private int index;
private string filename;
public static int SELECT_IMAGE = 1001;
Drawable drawable;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_addContact);
imageView = FindViewById<ImageView>(Resource.Id.load_image_imageView);
loadButton = FindViewById<Button>(Resource.Id.load_image_button);
addButton = FindViewById<Button>(Resource.Id.add_contact_button);
nameEditText = FindViewById<EditText>(Resource.Id.name_editText);
surnameEditText = FindViewById<EditText>(Resource.Id.surname_editText);
loadButton.Click += loadButtonClicked;
addButton.Click += addContactButtonClicked;
}
private void addContactButtonClicked(object sender, EventArgs e)
{
index = MainActivity.messages.Count;
Console.WriteLine(index);
Person newPerson = new Person(index, nameEditText.Text + " " + surnameEditText.Text, drawable.GetHashCode());
Intent intent = new Intent(this, typeof(MainActivity));
intent.PutExtra("person", JsonConvert.SerializeObject(newPerson));
StartActivity(intent);
}
private void loadButtonClicked(object sender, EventArgs e)
{
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == (int)Permission.Granted)
{
Intent = new Intent();
Intent.SetType("image/*");
Intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), SELECT_IMAGE);
}
else
{
ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.ReadExternalStorage }, 12);
}
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if ((requestCode == SELECT_IMAGE) && (resultCode == Result.Ok) && (data != null))
{
Android.Net.Uri uri = data.Data;
Bitmap bitmap = MediaStore.Images.Media.GetBitmap(ContentResolver, uri);
imageView.SetImageBitmap(bitmap);
}
else
{
Toast.MakeText(this.ApplicationContext, "You haven't picked an image", ToastLength.Short).Show();
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
if (requestCode == 12)
{
if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted))
{
Intent = new Intent();
Intent.SetType("image/*");
Intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), SELECT_IMAGE);
}
}
else
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Do you want to achieve the result like this GIF?
Based on your code, you need serveral steps to achieve it.
First of all, we should use Convert Bitmap to Base64 string to achieve it, we can create a MyUtils.cs
public class MyUtils
{
public static string ConvertBitMapToString(Bitmap bitmap)
{
byte[] bitmapData;
using (MemoryStream stream = new MemoryStream())
{
bitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Jpeg, 50, stream);
bitmapData = stream.ToArray();
}
string ImageBase64 = Convert.ToBase64String(bitmapData);
return ImageBase64;
}
public static Bitmap ConvertStringToBitmap(string mystr)
{
byte[] decodedString = Base64.Decode(mystr, Base64.Default);
Bitmap decodedByte = BitmapFactory.DecodeByteArray(decodedString, 0, decodedString.Length);
return decodedByte;
}
}
Then we should change the type of ImageId to string like following code.
public string ImageId // property
{
get { return imageId; } // get method
set { imageId = value; } // set method
}
Please change set the Image way in MainActiviy and Adapter.
Here is my demo, you can download it and refer to it.
https://github.com/851265601/TransferImageBtwActivities
Please help me. I can not create download URL Firebase storage. I want to when a pic upload into Firebase Storage, it save the URL to Firebase database. I tried a lot of way. But I didn't it. At the web of Firebase Database is not URL.
It show look this; imageUrl: "images/67824cbe-916e-4c74-82df-44227aa1d125". Its the name of Storage pics name.
My Upload Firebase Storage and Firebase Database activity is here;
package com.eraykalelioglu.ki_ta;
//imports here
public class BookActivity extends AppCompatActivity {
EditText editTextisim;
EditText editTextyazar;
Button buttonkitabikaydet;
Spinner spinnerGenres;
ImageView imageViewkitapkapakresmi;
DatabaseReference databaseKitaplar;
private Uri filePath;
private final int PICK_IMAGE_REQUEST = 1;
FirebaseStorage storage;
StorageReference storageReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book);
databaseKitaplar = FirebaseDatabase.getInstance().getReference("Kitaplar");
editTextisim = (EditText) findViewById(R.id.editTextisim);
editTextyazar = (EditText) findViewById(R.id.editTextyazar);
imageViewkitapkapakresmi = (ImageView) findViewById(R.id.imageViewkitapkapakresmi);
buttonkitabikaydet = (Button) findViewById(R.id.buttonkitabikaydet);
spinnerGenres = (Spinner) findViewById(R.id.spinnerGenres);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
storage = FirebaseStorage.getInstance();
storageReference = storage.getReference("images/");
buttonkitabikaydet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Kaydet();
}
});
imageViewkitapkapakresmi.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
chooseImage();
}
});
}
private void Kaydet(){
imageViewkitapkapakresmi.setDrawingCacheEnabled(true);
imageViewkitapkapakresmi.buildDrawingCache();
Bitmap bitmap = ((BitmapDrawable) imageViewkitapkapakresmi.getDrawable()).getBitmap();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
byte[] data = byteArrayOutputStream.toByteArray();
String mImageUrl = "images/" +UUID.randomUUID().toString();
final StorageReference storageReference = storage.getReference(mImageUrl);
UploadTask uploadTask = storageReference.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(BookActivity.this, "Yükleme Başarısız"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Task<Uri> downloadUrl = taskSnapshot.getMetadata().getReference().getDownloadUrl();
Log.d("onSuccess", "" + downloadUrl);
}
});
String isim = editTextisim.getText().toString().trim();
String yazar = editTextyazar.getText().toString().trim();
String genre = spinnerGenres.getSelectedItem().toString();
if (!TextUtils.isEmpty(isim) && !TextUtils.isEmpty(yazar)){
String id = databaseKitaplar.push().getKey();
Kitaplar kitaplar = new Kitaplar (id, isim, yazar, genre, mImageUrl);
databaseKitaplar.child(id).setValue(kitaplar);
Toast.makeText(this, "Kitabınız Başarıyla Kaydedildi", Toast.LENGTH_LONG).show();
startActivity(new Intent(BookActivity.this, Listesayfahali.class));
} else {
Toast.makeText(this, "Kitabın İsmi ve Yazarı Doldurulması Gereklidir", Toast.LENGTH_SHORT).show();
}
}
private void chooseImage(){
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Kitaba ait resmi seçin"), PICK_IMAGE_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null){
filePath = data.getData();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
imageViewkitapkapakresmi.setImageBitmap(bitmap);
}
catch (IOException e){
e.printStackTrace();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menuLogout:
FirebaseAuth.getInstance().signOut();
finish();
startActivity(new Intent(BookActivity.this, MainActivity.class));
break;
}
switch (item.getItemId()){
case R.id.menuKitaplar:
startActivity(new Intent(BookActivity.this, Listesayfahali.class));
}
return true;
}
}
My Database activity is here;
package com.eraykalelioglu.ki_ta;
public class Kitaplar {
String kitaplarId;
String kitaplarisim;
String kitaplaryazar;
String kitaplarGenre;
String mImageUrl;
public Kitaplar() {
}
public Kitaplar(String kitaplarId, String kitaplarisim, String kitaplaryazar, String kitaplarGenre, String imageUrl) {
this.kitaplarId = kitaplarId;
this.kitaplarisim = kitaplarisim;
this.kitaplaryazar = kitaplaryazar;
this.kitaplarGenre = kitaplarGenre;
mImageUrl =imageUrl;
}
public String getKitaplarId() {
return kitaplarId;
}
public String getKitaplarisim() {
return kitaplarisim;
}
public String getKitaplaryazar() {
return kitaplaryazar;
}
public String getKitaplarGenre() {
return kitaplarGenre;
}
public String getImageUrl() {return mImageUrl ; }
public void setImageUrl(String imageUrl){ this.mImageUrl= imageUrl; }
}`
I want to pass ArrayList via Intent to another activity. However, the code doesn't give any errors but List is always empty. Any idea what i'm doing wrong ? ty
Activity1
private ArrayList<ResimBean> rbList = new ArrayList<ResimBean>();
Bitmap bmp = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] thumbArray = stream.toByteArray();
Uri selectedImageUri = data.getData();
String fotopath = getRealPathFromURI(selectedImageUri);
ResimBean rb = new ResimBean(Parcel.obtain());
// rb.setResim(bar);
rb.setThumbnail(thumbArray);
rb.setPath(fotopath);
rbList.add(rb);
Intent intent = new Intent(getApplicationContext(), ResimListActivity.class);
intent.putParcelableArrayListExtra("reslist",rbList);
startActivityForResult(intent, 100);
Activity2
Bundle extras = getIntent().getExtras();
if (extras != null) {
try {
Intent i = getIntent();
ArrayList<ResimBean> rbList = i.getParcelableArrayListExtra("reslist");
} catch (Exception ex) {
String msg = ex.getMessage();
}
}
Its not giving any error but list is always empty.
EDIT
Added the code how i fill in list.
EDIT 2
Something wrong with my Parcelable class or what ?
public class ResimBean implements Parcelable {
private int Id;
private int HataBildirimId;
private byte[] Resim;
private byte[] Thumbnail;
public byte[] getThumbnail() {
return Thumbnail;
}
public void setThumbnail(byte[] thumbnail) {
Thumbnail = thumbnail;
}
private String Path;
public String getPath() {
return Path;
}
public void setPath(String path) {
Path = path;
}
public int getHataBildirimId() {
return HataBildirimId;
}
public void setHataBildirimId(int hataBildirimId) {
HataBildirimId = hataBildirimId;
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public byte[] getResim() {
return Resim;
}
public void setResim(byte[] resim) {
Resim = resim;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(HataBildirimId);
dest.writeByteArray(Resim);
dest.writeByteArray(Thumbnail);
}
public ResimBean(Parcel in) {
readFromParcel(in);
}
public void readFromParcel(Parcel in){
this.HataBildirimId = in.readInt();
this.Resim = new byte[in.readInt()];
this.Thumbnail = new byte[in.readInt()];
}
public static final Parcelable.Creator<ResimBean> CREATOR = new Parcelable.Creator<ResimBean>() {
#Override
public ResimBean createFromParcel(Parcel in) {
return new ResimBean(in);
}
#Override
public ResimBean[] newArray(int size) {
return new ResimBean[size];
}
};
The way you are showing, you create a new ArrayList<> and send it empty as extra via intent to the next activity.
Where exactly do you populate your ArrayList?
You should do something like this:
private ArrayList<ResimBean> rbList = new ArrayList<ResimBean>();
//populate rbList using adapter, then call intent
Intent intent = new Intent(getApplicationContext(), ResimListActivity.class);
intent.putParcelableArrayListExtra("reslist",rbList);
startActivityForResult(intent, 100);
Otherwise, the rbList you send as extra will always be empty. It sounds obvious but I don't know how you are doing it, so this is my best guess.
You can follow this tutorial:
http://aryo.lecture.ub.ac.id/android-passing-arraylist-of-object-within-an-intent/
I got it working like this
Bundle extras = this.getIntent().getExtras();
if (extras != null) {
try {
Intent i = getIntent();
ArrayList<ResimBean> rbList = (ArrayList<ResimBean>) i.getExtras().get("reslist");
Log.i("mytag", " "+i.getExtras().get("reslist").toString());
Log.i("mytag", " "+rbList.get(0).toString());
} catch (Exception ex) {
String msg = ex.getMessage();
}
}
With the rbList in Activity2 size=1,
With your code I was getting size=0
i wish to display my data and image which download from an URL but after i download the image from URL, the order of the image go wrong. I displayed my data and images using card view and recycle view, but the first image in first card go to second, while the second image at third card and the third one will missing and the first one will empty. Anyone can help me on this?
Below is my code. Tq
SimpleCardViewAdapter.java
public class SimpleCardViewAdapter extends RecyclerView.Adapter<SimpleCardViewAdapter.ViewHolder> {
private List<CardViewData> mDataset;
Bitmap downloadedBitmap;
ImageView row_image;
public SimpleCardViewAdapter(List<CardViewData> dataset) {
mDataset = dataset;
}
#Override
public ViewHolder onCreateViewHolder(final ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, int i) {
final CardViewData cardViewData = mDataset.get(i);
viewHolder.mTitle.setText(cardViewData.getTitle());
viewHolder.mDescription.setText(cardViewData.getDescription());
String var = cardViewData.getImage();
new Thread(new getImageTask(var)).start();
viewHolder.mImage.setImageBitmap(downloadedBitmap);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Title: " + cardViewData.getTitle(), Toast.LENGTH_SHORT).show();
}
});
}
class getImageTask implements Runnable {
String imageUrl;
getImageTask(String imgUrl){
imageUrl = imgUrl;
}
#Override
public void run() {
try {
URL url = new URL(imageUrl);
downloadedBitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Message msg = new Message();
Bundle b = new Bundle();
b.putString("mfeApi", "1");
msg.setData(b);
handlerGroupedProductsImage.sendMessage(msg);
}
}
Handler handlerGroupedProductsImage = new Handler() {
public void handleMessage(Message msg) {
Bundle b = msg.getData();
String done = b.getString("mfeApi");
};
};
#Override
public int getItemCount() {
return mDataset == null ? 0 : mDataset.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public TextView mDescription;
public ImageView mImage;
public ViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.row_title);
mDescription = (TextView) itemView.findViewById(R.id.row_description);
mImage = (ImageView) itemView.findViewById(R.id.row_image);
}
}
Activity.java
private void getData() {
try {
final String toSend = "http://www.test.com.my/test/api/kipcard_helpAPI.php";
new Thread(new Runnable() {
#Override
public void run() {
URL url = null;
HttpURLConnection conn = null;
String receivedString = null;
try {
url = new URL(toSend);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
InputStream in = new BufferedInputStream(conn.getInputStream());
receivedString = IOUtils.toString(in, "UTF-8");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Message msg = new Message();
Bundle b = new Bundle();
b.putString("mfeApi", receivedString);
msg.setData(b);
hGet.sendMessage(msg);
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
Handler hGet = new Handler() {
public void handleMessage(Message msg) {
Bundle b = msg.getData();
String s = b.getString("mfeApi");
items = s.split("\\|\\|");
size = items.length;
List <CardViewData> list = new ArrayList<CardViewData>();
for(int i = 0 ; i <= size-3 ; i+=3){
Log.d("here",items[i] +"" );
//new Thread(new getImageTask(imahr)).start();
list.add(new CardViewData(items[i+2], items[i+3], items[i+1]));
}
mAdapter = new SimpleCardViewAdapter(list);
mRecyclerView.setAdapter(mAdapter);
};
};
The problem is here:
new Thread(new getImageTask(var)).start();
viewHolder.mImage.setImageBitmap(downloadedBitmap);
As the thread do it's job parallel not synchronously downloadedBitmap can hold another's thread "old" result.
Instead of
new Thread(new getImageTask(var)).start();
viewHolder.mImage.setImageBitmap(downloadedBitmap);
Try using
final int position = i;
viewHolder.position = i;
new AsyncTask<Object, Void, Bitmap>() {
private AlbumViewHolder v;
#Override
protected Bitmap doInBackground( Object[] params ) {
v = (AlbumViewHolder) params[ 0 ];
// download here your image
return b;
}
#Override
protected void onPostExecute( Bitmap result ) {
super.onPostExecute( result );
if ( v.position == position && result != null ) {
// If this item hasn't been recycled already, hide the
// progress and set and show the image
v.mImageView.setImageBitmap( result );
v.mImageView.setVisibility( View.VISIBLE );
v.mProgressBar.setVisibility( View.GONE );
}
}
}.execute( viewHolder );
and in ViewHolder :
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public TextView mDescription;
public ImageView mImage;
public int position;
public ViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.row_title);
mDescription = (TextView) itemView.findViewById(R.id.row_description);
mImage = (ImageView) itemView.findViewById(R.id.row_image);
}
}
And one more thing - your ViewHolder should have position parameter. And think about caching.
Try this:
add Context to your constructor
public SimpleCardViewAdapter(List<CardViewData> dataset, Activity activity){
this.mActivity = activity;
}
change in onBindViewHolder method:
new Thread(new getImageTask(var, viewHolder.mImage)).start();
and change your task like this:
class getImageTask implements Runnable {
String imageUrl;
ImageView imageView
getImageTask(String imgUrl, ImageView imageView){
imageUrl = imgUrl;
this.imageView = imageView;
}
#Override
public void run() {
try {
URL url = new URL(imageUrl);
//change this line also
Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
//set you downloaded image now...
//new change ....
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
//Your code to run in GUI thread here
if(bitmap != null)
imageView.setImageBitmap(bitmap);
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Message msg = new Message();
Bundle b = new Bundle();
b.putString("mfeApi", "1");
msg.setData(b);
handlerGroupedProductsImage.sendMessage(msg);
}
}
***but it will not cache bitmap, every time you scroll your recycler inside app it will download it again and again.
I'm developing an Android app but I'm a newbie and I got stuck...
My ListView single element has an ImageView and some TextViews, but sometimes (when I scroll the page and there are more than 7-8 elements) it doesn't display the right image in the right row.
I'm using a custom Image Loader to manage the downloaded images.
Here's my Adapter:
public class AddVideogameActivityAdapter extends BaseAdapter {
private ArrayList<Videogame> videogames;
private Typeface typefaceMedium;
private Typeface typefaceLight;
private ImageLoader loader;
private LayoutInflater mInflater;
public AddVideogameActivityAdapter(Context context, ArrayList<Videogame> results) {
videogames = results;
mInflater = LayoutInflater.from(context);
typefaceMedium = Typeface.createFromAsset(context.getAssets(), "Roboto-Medium.ttf");
typefaceLight = Typeface.createFromAsset(context.getAssets(), "Roboto-Light.ttf");
loader = new ImageLoader(context);
}
public int getCount() {
return videogames.size();
}
public Object getItem(int position) {
return videogames.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_element,null);
holder = new ViewHolder();
holder.imgView = (ImageView) convertView.findViewById(R.id.thumbView);
holder.txtName = (TextView) convertView.findViewById(R.id.elementView);
holder.txtPlatform = (TextView) convertView.findViewById(R.id.elementView2);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
try {
Videogame vgame = (Videogame) videogames.get(position);
holder.txtName.setText(vgame.getTitle());
holder.txtName.setTypeface(typefaceMedium);
holder.txtPlatform.setText(videogames.get(position).getPlatform());
holder.txtPlatform.setTypeface(typefaceLight);
holder.imgUrl = videogames.get(position).getImage();
loader.display(holder.imgUrl, holder.imgView, R.drawable.youtube_icon);
}
catch (Exception e) {
e.printStackTrace();
Log.e(com.example.ludos2_0.MainActivity.TAG,
"Exception: " + e.getLocalizedMessage());
}
return convertView;
}
static class ViewHolder {
TextView txtName;
TextView txtPlatform;
public String imgUrl;
ImageView imgView;
}
}
Sorry for my english and thank you for your help!
EDIT:
Here's also the Loader:
public class ImageLoader implements ComponentCallbacks2 {
private TCLruCache cache;
public ImageLoader(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass() * 1024 * 1024;
cache = new TCLruCache(memoryClass);
}
public void display(String url, ImageView imageview, int defaultresource) {
imageview.setImageResource(defaultresource);
Bitmap image = cache.get(url);
if (image != null) {
imageview.setImageBitmap(image);
}
else {
new SetImageTask(imageview).execute(url);
}
}
private class TCLruCache extends LruCache<String, Bitmap> {
public TCLruCache(int maxSize) {
super(maxSize);
}
}
private class SetImageTask extends AsyncTask<String, Void, Integer> {
private ImageView imageview;
private Bitmap bmp;
public SetImageTask(ImageView imageview) {
this.imageview = imageview;
}
#Override
protected Integer doInBackground(String... params) {
String url = params[0];
try {
bmp = getBitmapFromURL(url);
if (bmp != null) {
cache.put(url, bmp);
}
else {
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
}
return 1;
}
#Override
protected void onPostExecute(Integer result) {
if (result == 1) {
imageview.setImageBitmap(bmp);
}
super.onPostExecute(result);
}
private Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection
= (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
}
RE-EDIT
Activity code:
public class AddVideogameActivity extends ListActivity {
private TextView searchField = null;
private final Handler handler = new Handler();
private ArrayList<Videogame> videogamesList = null;
private static AddVideogameActivity mContext = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_book);
mContext = this;
searchField = (TextView) findViewById(R.id.searchField);
searchField.setMaxLines(1);
searchField.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
searchField.setHint("");
}
});
// Setup the list view and its listener
getListView().setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.d(MainActivity.TAG,
"AddBookActivity ---> AddButton:onClick()");
// Sets typefaces for TextView
String videogameId = videogamesList.get(position).getId();
String videogameName = videogamesList.get(position).getTitle();
String thumbnail = videogamesList.get(position).getThumbnail();
String description = videogamesList.get(position)
.getDescription();
String image = videogamesList.get(position).getImage();
String platform = videogamesList.get(position).getPlatform();
if (videogameName != null && videogameName.length() > 0
&& thumbnail != null && thumbnail.length() > 0
&& description != null && description.length() > 0
&& image != null && image.length() > 0
&& platform != null && platform.length() > 0) {
if (ListsManager.getInstance().addVideogame(
new Videogame(videogameId, videogameName,
thumbnail, image, description, platform)) == 0) {
Log.d(MainActivity.TAG,
"AddBookActivity --> Videogame:[" + videogameId
+ "#" + videogameName + "]");
Toast toast = Toast.makeText(mContext, "["
+ videogameName + "] Saved !",
Toast.LENGTH_LONG);
toast.show();
} else {
Log.e(MainActivity.TAG,
"AddBookActivity --> Error ! Videogame already in the list ! ");
Toast toast = Toast.makeText(mContext,
"Error! Videogame already in the list!",
Toast.LENGTH_LONG);
toast.show();
}
} else {
Log.e(MainActivity.TAG,
"AddBookActivity --> Error ! Invalid Videogame Name or Thumbnail or Id or Deck");
Toast toast = Toast
.makeText(
mContext,
"Error ! Invalid Videogame Name or Thumbnail or Id or Deck",
Toast.LENGTH_LONG);
toast.show();
}
Intent newIntent = new Intent(getApplicationContext(),
MainActivity.class);
startActivity(newIntent);
}
});
// Setup the search button and its listener
Button searchButton = (Button) findViewById(R.id.searchButton);
searchButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(com.example.ludos2_0.MainActivity.TAG, "Search Game ...");
String searchInputString = searchField.getText().toString();
if (searchInputString != null && searchInputString.length() > 0) {
try {
String requestURL = ("http://www.giantbomb.com/api/search/?api_key=fcf60d6d67b98b0d17b3905d1a90b3fd31ed1e8e&format=json&query="
+ Uri.encode(searchInputString) + "&resources=game");
// String requestURL =
// String.format("https://gdata.youtube.com/feeds/api/videos?v=2&alt=jsonc&category=Music&orderby=relevance&q=%s",Uri.encode(searchInputString));
Log.d(com.example.ludos2_0.MainActivity.TAG, requestURL);
DownloadGiantBombJSONData giantbombAsyncTask = new DownloadGiantBombJSONData();
giantbombAsyncTask.execute(new String[] { requestURL });
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
if (videogamesList == null)
videogamesList = new ArrayList<Videogame>();
else
updateVideogamesListView(videogamesList);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.add_book, menu);
return true;
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
public void updateVideogamesListView(ArrayList<Videogame> values) {
AddVideogameActivityAdapter adapter = new AddVideogameActivityAdapter(this, values);
setListAdapter(adapter);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
The other classes involved in building the ListView are the REST classes and the AsyncTask class that downloads and parses the JSon files.
What does your ListView look like, does it look like this:
<ListView android:id="#id/android:list"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip" ></ListView>
Especially the id of the ListView. Check your layout file, probably the bug exists there.