2017-02-10 91 views
1

当前我使用Picasso这个图书馆作为图像加载。我试图使用这个库在listview中加载1000个图像,但它需要时间,并且还堵塞了我的应用程序。我可以为流畅的用户体验做些什么?我在适配器中使用以下代码进行图像加载。如何在Android中使用Piccaso图像加载库来平滑图像加载?

Picasso.with(context).load(new File(path + list.get(position))) 
        .centerCrop() 
        .resize(150, 150) 
        .error(R.mipmap.ic_launcher) 
        .into(img); 

回答

0

我也有过,当我试图开发库的应用程序并加载许多图像类似的问题。

对于解决方案,我已经更改了下面的picasso版本,它工作得很好。

附加按照您的应用级的build.gradle中到ListView

repositories { 
    maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } 
} 

compile 'com.squareup.picasso:picasso:2.5.3-SNAPSHOT' 
1

加载1000张图像是要造成大量的内存问题,并会减慢您的设备。

我以前有过这样的问题,我发现解决方案是使用RecyclerView而不是ListView

A RecyclerView就是这样做的,它不是每次创建和膨胀一个新视图,而是回收刚刚消失的视图并更改它的内容,因此可以将其添加到RecyclerView的底部。

看一看下面这个示例代码:

首先添加RecyclerViewGradle

compile 'com.android.support:appcompat-v7:25.0.1' 
compile 'com.android.support:recyclerview-v7:25.0.1' 

添加RecyclerView为xml

<android.support.v7.widget.RecyclerView 
     android:id="@+id/recyclerView" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:animationCache="false" 
     android:scrollingCache="false" 
     android:smoothScrollbar="true" /> 

初始化RecyclerViewActivity

RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView); 
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this); 
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); 
recyclerView.setLayoutManager(mLayoutManager); 

然后创建RecyclerView适配器

public class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder> { 

Context context; 
public ArrayList<EventObject> eventList; 
private String category; 

/** 
* Viewholder class for view reuse 
*/ 
public static class ViewHolder extends RecyclerView.ViewHolder { 
    private PEWImageView img_main; 
    private RelativeLayout layoutItem; 
    private TextView txt_event_name; 
    private TextView txt_event_details; 
    private TextView txt_going_to; 
    private View gradient_view; 

    /** 
    * Viewholder contructor where all assignments take place so this is only done once 
    * @param itemView 
    * @param context 
    */ 
    public ViewHolder(View itemView, Context context) { 
     super(itemView); 
     img_main = (PEWImageView) itemView.findViewById(R.id.img_main); 
     txt_event_details = (TextView) itemView.findViewById(R.id.txt_event_details); 
     txt_event_name = (TextView) itemView.findViewById(R.id.txt_event_name); 
     txt_going_to = (TextView) itemView.findViewById(R.id.txt_going_to); 
     gradient_view = itemView.findViewById(R.id.gradient_view); 
     layoutItem = (RelativeLayout) itemView.findViewById(R.id.rl_event_item); 

     txt_event_name.setTypeface(FontClass.getOpenSansBold(context)); 
     txt_event_details.setTypeface(FontClass.getOpenSansLight(context)); 
     txt_going_to.setTypeface(FontClass.getOpenSansLight(context)); 
    } 

    /** 
    * Sets up UI for each item 
    * @param context 
    * @param eventObject 
    * @param category 
    * @throws JSONException 
    * @throws ParseException 
    */ 
    public void bindView(final Context context, final EventObject eventObject, String category) throws JSONException, ParseException { 

     /** 
     * Handles special characters 
     */ 
     txt_event_name.setText(Html.fromHtml(eventObject.getEventName())); 

     /** 
     * Checks if venue name contains the name of the town 
     */ 
     if (eventObject.getVenueName().contains(eventObject.getTown())) { 
      txt_event_details.setText(eventObject.getVenueName() + ", " + getFormattedDate(eventObject.getEventDate())); 
     } else { 
      txt_event_details.setText(eventObject.getVenueName() + ", " + eventObject.getTown() + ", " + getFormattedDate(eventObject.getEventDate())); 
     } 

     /** 
     * Checks if event should have yellow box above 
     */ 
     try { 
      if (eventObject.getFeeFreeStatus() == 1) { 
       txt_going_to.setVisibility(category.equalsIgnoreCase("no fees") ? View.GONE : View.VISIBLE); 
       txt_going_to.setText("Fee free tickets available"); 
      } else { 
       txt_going_to.setVisibility(Integer.parseInt(eventObject.getGoingToCount()) >= 200 ? View.VISIBLE : View.GONE); 
       txt_going_to.setText("Popular event: " + eventObject.getGoingToCount() + " going"); 
      } 
     } catch (Exception e){ 
      e.printStackTrace(); 
      txt_going_to.setVisibility(View.GONE); 
     } 

     /** 
     * Sets colour gradient over image 
     */ 
     if (eventObject.getHeaderHex() != null && !eventObject.getHeaderHex().equals("")) { 
      GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[]{Color.TRANSPARENT, alterColor(Color.parseColor(eventObject.getHeaderHex()), 0.2f)}); 
      gd.setCornerRadius(0f); 

      gradient_view.setBackground(gd); 
     } 

     layoutItem.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       ((HomeActivity) context).setEventProfileFrag(eventObject.getFullJsonObject(), null); 
      } 
     }); 

     /** 
     * Loads image in to layout item 
     */ 
     Picasso.with(context) 
       .load(eventObject.getImageUrl()) 
       .placeholder(R.drawable.ic_skiddle_placeholder) 
       .noFade() 
       .into(img_main); 

    } 

    /** 
    * Formats the date returned from the API 
    * @param dateString 
    * @return 
    * @throws ParseException 
    */ 
    private String getFormattedDate(String dateString) throws ParseException { 

     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.UK); 
     Date newDate = format.parse(dateString); 
     format = new SimpleDateFormat("EEEE dd MMMM", Locale.UK); 
     String date = format.format(newDate); 
     return date; 
    } 
} 

/** 
* Creates the view holder 
* @param parent 
* @param viewType 
* @return 
*/ 
@Override 
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_event_list_item, parent, false); 
    return new ViewHolder(itemView, parent.getContext()); 
} 

/** 
* Binds the viewholder to the recyclerview 
* @param holder 
* @param position 
*/ 
@Override 
public void onBindViewHolder(final ViewHolder holder, int position) { 
    try { 
     holder.bindView(context, eventList.get(position), this.category); 
    } catch (JSONException e) { 
     e.printStackTrace(); 
    } catch (ParseException e) { 
     e.printStackTrace(); 
    } 
} 

/** 
* Returns the item id 
* @param position 
* @return 
*/ 
@Override 
public long getItemId(int position) { 
    return position; 
} 

/** 
* Returns the number of items in the adapter 
* @return 
*/ 
@Override 
public int getItemCount() { 
    return eventList.size(); 
} 

/** 
* Constructor 
* @param context 
* @param eventList 
* @param category 
*/ 
public EventListAdapter(Context context, ArrayList<EventObject> eventList, String category) { 
    this.context = context; 
    this.eventList = eventList; 
    this.category = category; 
    setHasStableIds(true); 
} 

/** 
* Method to add items to the adapter (for pagination) 
* @param eventList 
*/ 
public void addItems(ArrayList<EventObject> eventList) { 
    this.eventList.addAll(eventList); 
    notifyDataSetChanged(); 
} 

/** 
* Method to darken the head hex colour for the gradient overlay 
* @param color 
* @param factor 
* @return 
*/ 
public static int alterColor(int color, float factor) { 
    int a = (color & (0xFF << 24)) >> 24; 
    int r = (int) (((color & (0xFF << 16)) >> 16) * factor); 
    int g = (int) (((color & (0xFF << 8)) >> 8) * factor); 
    int b = (int) ((color & 0xFF) * factor); 
    return Color.argb(a, r, g, b); 
} 
} 

然后,只需将适配器设置为RecyclerView了活动。

您可以更改此适配器以了解您的需要,但主要概念在此处。