2016-11-14 2 views
11

Я показываю список контактов в recyclerview. Я показываю изображения профиля контакта, сначала загружаю эти изображения с сервера, а затем сохраняю эти изображения во внешней памяти.Lazy Загрузка не работает должным образом

Затем загружает изображения с внешнего хранилища. Я вижу, что изображения загружены, но когда я прокручиваю, я вижу несколько изображений на секунду или два, после чего они исчезают, и я вижу значок изображения по умолчанию.

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactHolder> { 


    private List<Contact> contactList; 
    File myDir1; 
    private Activity mContext; 

    private Boolean fileExists; 
    private File file; 
    private static final int MY_PERMISSIONS_REQUEST_CALL= 20; 

    public ContactAdapter(Activity context, List<Contact> contactList) { 
     this.contactList = contactList; 
     this.mContext = context; 
    } 

    @Override 
    public ContactHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 

     View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout,null); 
     ContactHolder mh = new ContactHolder(v); 

     return mh; 
    } 

    @Override 
    public void onBindViewHolder(final ContactHolder contactHolder, int i) { 

     final Contact contact = contactList.get(i); 
     // Log.e("Imagename",""+"http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg");//+feedItem.getThumbnail()); 

     Target target = new Target() { 

      @Override 
      public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { 

       // your code here ... 

       bitmap = Bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.8), (int)(bitmap.getHeight()*0.8), true); 

       contactHolder.thumbnail.setImageBitmap(bitmap); 

       Log.e("ProfileImage", contact.getmProfileImage()); 

       SaveImages(bitmap, contact.getmProfileImage()); 

      } 

      @Override 
      public void onBitmapFailed(Drawable errorDrawable) { 
       contactHolder.thumbnail.setImageDrawable(errorDrawable); 
       // do error handling as required 
      } 

      @Override 
      public void onPrepareLoad(Drawable placeHolderDrawable) { 
       contactHolder.thumbnail.setImageDrawable(placeHolderDrawable); 
      } 
     }; 

     contactHolder.thumbnail.setTag(target); 

     String url = ServiceUrl.getBaseUrl() + ServiceUrl.getImageUserUrl() + contact.getmProfileImage(); 

     Log.e("url",url); 

     if(contact.getmProfileImage().equals("")) 

     { 

      file = new File(""); 

      fileExists = file.exists(); 

      contactHolder.thumbnail.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_account_circle_black_48dp)); 
     } 
     else { 

      file = new File(Environment.getExternalStorageDirectory() + "/ContactProfileImages/" + contact.getmProfileImage()); 

      fileExists = file.exists(); 
     } 

     if(fileExists) 
     { 

      Log.e("fileExists",file.getAbsolutePath()); 

      BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
      Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(), bmOptions); 

      contactHolder.thumbnail.setImageBitmap(bitmap); 

     } 

     else { 

      Log.e("Picasso",file.getAbsolutePath()); 

      Picasso.with(mContext).load(url) 
        .error(R.drawable.ic_account_circle_black_24dp) 
        .placeholder(R.drawable.ic_account_circle_black_24dp) 
        .into(target); 
     } 

     contactHolder.title.setText(contact.getmUserName()); 
     //feedListRowHolder.genre.setText(Html.fromHtml(feedItem.getGenre())); 

    } 

    @Override 
    public int getItemCount() { 
     return (null != contactList ? contactList.size() : 0); 
    } 

    public void SaveImages(Bitmap bitmap,String profileName) 
    { 

     try { 
      String root = Environment.getExternalStorageDirectory().getPath(); 
      File myDir = new File(root +"/ContactProfileImages"); 

      if (!myDir.exists()) { 
       myDir.mkdirs(); 
      } 

      // String name = new Date().toString();= 
      String name = profileName; 
      File myDir1 = new File(myDir, name); 
      if(!myDir1.exists()) { 
       FileOutputStream out = new FileOutputStream(myDir1); 
       bitmap.compress(Bitmap.CompressFormat.PNG,100,out); 

       out.flush(); 
       out.close(); 
      } 


     } catch(Exception e){ 
      // some action 
     } 

     //myDir1= imageFilePath1.getprofile(); 

    } 


    public class ContactHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
     protected CircleImageView thumbnail; 
     protected TextView title; 

     public ContactHolder(View view) { 
      super(view); 
      this.thumbnail = (CircleImageView) view.findViewById(R.id.thumbnail); 
      this.title = (TextView) view.findViewById(R.id.title); 
      view.setOnClickListener(this); 

     } 

     @Override 
     public void onClick(View v) { 

      final Contact contact = contactList.get(getAdapterPosition()); 

      final Dialog dialog = new Dialog(mContext); 
      dialog.setCanceledOnTouchOutside(true); 
      dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 
      dialog.setContentView(R.layout.custom); 
      final Window window = dialog.getWindow(); 

      WindowManager.LayoutParams wlp =window.getAttributes(); 
      wlp.gravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP; 
      wlp.y=320; 
      window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 
      window.setAttributes(wlp); 

      // set the custom dialog components - text, image and button 
      TextView txtusername = (TextView) dialog.findViewById(R.id.txtusername); 
      TextView txtmobile = (TextView) dialog.findViewById(R.id.txtmobile); 
      TextView txtemail = (TextView) dialog.findViewById(R.id.txtemail); 

      txtusername.setText(contact.getmUserName()); 
      txtemail.setText(contact.getmEmailId()); 
      txtmobile.setText(contact.getmMobileNo()); 

      SquareImageView image = (SquareImageView) dialog.findViewById(R.id.image); 
      ImageView image1 = (ImageView) dialog.findViewById(R.id.image1); 
      ImageView image2 = (ImageView) dialog.findViewById(R.id.image2); 
      ImageView image3 = (ImageView) dialog.findViewById(R.id.image3); 

      if(contact.getmProfileImage().equals("")) 

      { 
       image.setImageDrawable(ContextCompat.getDrawable(mContext,R.drawable.profile_icon)); 
      } 
      else { 
       File file = new File(Environment.getExternalStorageDirectory() + "/ContactProfileImages/" + contact.getmProfileImage()); 
       BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
       Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(), bmOptions); 

       image.setImageBitmap(bitmap); 
      } 

      image1.setImageResource(R.drawable.ic_call_black_24dp); 
      image2.setImageResource(R.drawable.ic_textsms_black_24dp); 
      image3.setImageResource(R.drawable.ic_email_black_24dp); 

      image2.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 

        Uri sms_uri = Uri.parse("smsto:" + contact.getmMobileNo()); 
        Intent sms_intent = new Intent(Intent.ACTION_SENDTO, sms_uri); 
        mContext.startActivity(sms_intent); 
        dialog.dismiss(); 

       } 
      }); 

      image1.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 

         Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + contact.getmMobileNo())); 
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 
         mContext.startActivity(intent); 
         dialog.dismiss(); 
       } 
      }); 

      image3.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        Intent email = new Intent(Intent.ACTION_SEND); 
        email.putExtra(Intent.EXTRA_EMAIL, new String[]{contact.getmEmailId()}); 
        email.setType("message/rfc822"); 
        mContext.startActivity(Intent.createChooser(email, "Choose an Email client :")); 

       } 
      }); 

      Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK); 
      // if button is clicked, view all information custom dialog 

      dialogButton.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 

        ((MainActivity)mContext).finish(); 

        Intent intent = new Intent(mContext,DetailViewActivity.class); 
        intent.putExtra("contact",contact); 
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 
        mContext.startActivity(intent); 

        dialog.dismiss(); 


       } 
      }); 
      dialog.show(); 

     } 
    } 
} 

EDIT: Я искал по тому же вопрос с библиотекой Picasso, когда мы загружаем изображения с сервера, для этого я получил решение от SO, как:

recyclerView.setHasFixedSize(true); 
    recyclerView.setItemViewCacheSize(20); 
    recyclerView.setDrawingCacheEnabled(true); 
    recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); 

И это работало, когда я загрузка изображения с сервера, но когда я загружаю изображения из внешнего хранилища, проблема существует.

Может ли кто-нибудь помочь в этом, пожалуйста? Спасибо ..

+0

это может быть не связано, но взгляните на это [ссылка] мерзавца (https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews-and-RecyclerView#implementing-with- recyclerview), вместо '.post' использовать' .postDelayed' –

+0

где использовать .postDelayed ?? @ Mr.Z – Sid

+0

@Sid: проверьте код на странице http://androidexample.com/Download_Images_From_Web_And_Lazy_Load_In_ListView_-_Android_Example/index.php?view=article_discription&aid=112 – avinash

ответ

4

Then Загрузка изображений из внешнего хранилища. Я вижу, что загружаются изображения , но по мере прокрутки я могу увидеть некоторые изображения на секунду или два, затем они исчезают, и я вижу значок изображения по умолчанию.

Это потому, что вы используете целевой обратный вызов в пикассо. И обратные вызовы называются немного запоздалыми, когда вы прокручиваете список. Просто удалите цель и используйте изображение в Picasso, оно должно работать нормально. Также вам не нужно кэшировать растровые изображения самостоятельно, поскольку Picasso делает это за вас.

public void onBindViewHolder(final ContactHolder contactHolder, int i) { 
    final Contact contact = contactList.get(i); 
    // Log.e("Imagename",""+"http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg");//+feedItem.getThumbnail()); 

    String url = ServiceUrl.getBaseUrl() + ServiceUrl.getImageUserUrl() + contact.getmProfileImage(); 
    Log.e("url",url); 

    if(contact.getmProfileImage().equals("")) { 
     file = new File(""); 
     fileExists = file.exists(); 
     contactHolder.thumbnail.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_account_circle_black_48dp)); 
    } else { 
     file = new File(Environment.getExternalStorageDirectory() + "/ContactProfileImages/" + contact.getmProfileImage()); 
     fileExists = file.exists(); 
    } 

    Log.e("Picasso",file.getAbsolutePath()); 

    Picasso.with(mContext).load(url) 
     .error(R.drawable.ic_account_circle_black_24dp) 
     .placeholder(R.drawable.ic_account_circle_black_24dp) 
     .into(contactHolder.thumbnail); 

    contactHolder.title.setText(contact.getmUserName()); 
    //feedListRowHolder.genre.setText(Html.fromHtml(feedItem.getGenre())); 
} 
+0

, но мне нужно, чтобы местоположение сохраненного изображения отображалось в другом действии, и я обнаружил, что мы не можем получить путь кэш-изображения, сохраненного на пикассо, поэтому я следовали этому пути, чтобы сохранить изображения во внешнем хранилище и использовать его. – Sid

+1

вам не нужно место, чтобы показать одно и то же изображение в другой деятельности, вам нужен только URL-адрес изображения. Picasso сохраняет изображение с URL-адресом изображения в качестве ключа. Поэтому, когда вам нужно изображение в какой-либо другой деятельности или фрагменте, оно может быть восстановлено из кеша, если оно уже сохранено – Sam

0

Я могу ошибиться, но ваша проблема может быть вызвана тем, что вы используете Contact, что вы получили от вашего набора данных по позиции макета, но так как вы используете его asynchroniously в onBitmapLoaded обратного вызова, позиция может быть уже изменен в этот момент. Так что все, что вам нужно использовать положение адаптера следующим образом:

@Override 
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { 

    // your code here ... 

    Contact c = contactList.get(contactHolder.getAdapterPosition()); 

    bitmap = Bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.8), (int)(bitmap.getHeight()*0.8), true); 

    contactHolder.thumbnail.setImageBitmap(bitmap); 

    Log.e("ProfileImage", c.getmProfileImage()); 

    SaveImages(bitmap, c.getmProfileImage()); 
} 

Я не уверен, что это было бы полезно, но давайте попробуем, и я надеюсь, что это будет :)

+0

попробовал это, но проблема все еще не исчезла .. :-(@ rom4ek – Sid

0

Если вы хотите просто загрузить изображение, то почему вам нужно хранить его во внешнем хранилище. Если вы должны хранить его для каких-либо других целей, тогда сохраните его, но когда вы покажете его в ImageView, используйте, пожалуйста, любой сторонний api, например Picasso или Universal Image Loader он ленивый загрузка, а также все типы управления памятью кэш-памяти также подтверждают многие проявления фазальности.

Надеется, что это поможет вам

+0

Я сохраняю изображения в папке, потому что если пользователь в автономном режиме, он должен увидеть список. Поэтому я хочу загрузить изображения из папки, когда пользователь отключен. – Sid

+0

, но мне нужно, чтобы местоположение сохраненного изображения отображалось в другом действии, и я обнаружил, что мы не можем получить путь кэш-изображения, сохраненного на picasso, поэтому я следил за этим способом, чтобы сохранить изображения во внешнем хранилище и использовать его . @sanat chandravanshi – Sid

0

операции, как загрузка изображения должны быть выполнено с использованием AsyncTask в фоновом потоке.

+0

Не могли бы вы направить меня с кодом для загрузки изображений из внешнего хранилища из задачи async в recyclerview? – Sid

1

используйте этот код в своем классе приложения, чтобы применить настройку в целом приложении.

final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 
// Use 1/8th of the available memory for this memory cache. 
final int cacheSize = maxMemory/8; 
Picasso.Builder builder = new Picasso.Builder(getApplicationContext()); 
builder.memoryCache(new LruCache(cacheSize)); 
Picasso built = builder.build(); 
built.setIndicatorsEnabled(true);// it will show indicator where it downloaded from 
built.setLoggingEnabled(false); 
Picasso.setSingletonInstance(built); 

Теперь передать URL Пикассо, чтобы загрузить его для просмотра .Если вы имеете дело с большим изображением вы можете изменить размер изображения и для более быстрой загрузки.

Picasso 
    .with(mContext) 
    .load(url) 
    .error(R.drawable.on_error) 
    .placeholder(R.drawable.place_holder) 
    //.resize(custom_width,custom_height) put custom_height to 0 if you want to maintain aspect ratio 
    .into(your_view); 
+0

Я хочу загрузить изображения из внешней памяти, могу ли я загрузить его с помощью пикассо? @NANDAN KUMAR SINGH – Sid

+0

да! , вы можете загрузить из внешней памяти, пропустив изображение uri. –

+0

не могли бы вы показать мне пример? @NANDAN KUMAR SINGH – Sid

0
  • аждые изображения сколько MB это. Для примера: Если изображение - 1mb или 500kb потребуется больше времени, чтобы загрузить изображения в фон, и после его загрузки он сохранится в catche.That значит ., Первый раз, только на скачивание займет только некоторое время.

  • во второй раз, эти изображения из catche.It будет отображать все изображения за доли секунды.

  • Использование Volley - для ускорения и скольжения - для управления памятью.

    Glide 
        .with(context) 
        .load(rowItem.getPosteduserpostimage()) 
        .asBitmap() 
        .diskCacheStrategy(DiskCacheStrategy.SOURCE) 
        .fitCenter() 
        .placeholder(R.drawable.load_image) 
        .error(R.drawable.cancel_image) 
        .into(holder.ivPostedImageNew); 
    
  • См here как загружать большой размер bitmap.You нужно уменьшать изображение.

  • В противном случае, когда я загружаю каждое изображение, я обрезал библиотеку .Он позаботится о масштабировании большого растрового изображения. , например: 5mb Изображения увеличатся до 180 kb.

  • Проверить это CropImage lib масштаб вниз большего размера images.Even если пользователь не обрезать изображение, просто выбрать всю часть, когда кадрирование, он будет масштабироваться до 5 мб до 180kb.Image Качество тоже хорошее.

Я думаю, что без урожая также вы можете использовать следующий код для масштабирования вниз image.You может увидеть этот код в том, что:

private void startCropImage() { 

    Intent intent = new Intent(this, CropImage.class); 

    intent.putExtra(CropImage.IMAGE_PATH, mFileTemp.getPath()); 
    intent.putExtra(CropImage.SCALE, true); 
    intent.putExtra(CropImage.ASPECT_X, 0); //3 for aspect ratio 
    intent.putExtra(CropImage.ASPECT_Y, 0); //2 for aspect ratio 

    startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE); 
} 
  • А также не использовать вложенный вид прокрутки внутри recyclerview.

 Смежные вопросы

  • Нет связанных вопросов^_^