Tôi đã tìm kiếm các chuỗi SO để trả lời nhưng không thể tìm ra vấn đề của tôi từ cuộc thảo luận trước. Tôi có một listview tải khoảng 50 hình ảnh (nó được sử dụng để được khoảng 100 nhưng điều này hầu như không tải bất kỳ hình ảnh ở tất cả). Sau khi lấy nội dung JSON của tôi (bao gồm cả URL hình ảnh) từ một điểm cuối api, thông qua một bộ điều hợp, mã của tôi đặt nó bên trong listview.Picasso giữ tải lại hình ảnh trong khi di chuyển lên trên trong chế độ xem danh sách, tải chậm
Hiện tại, với 50 hình ảnh, picasso sẽ tải một hình ảnh tại một thời điểm khi tôi cuộn xuống trên nguồn cấp dữ liệu. Tôi cảm thấy như thể giữ cuộn cố định trên một mục trong listview sẽ làm cho hình ảnh đó tải nhanh hơn. Tuy nhiên, khi tôi cuộn lên, nó sẽ đặt trình giữ chỗ trở lại và tải lại hình ảnh. Có cách nào để giải quyết vấn đề này không?
public class MainActivity extends Activity {
private List<Post> myPosts = new ArrayList<Post>();
protected String[] mBlogPostTitles;
public static final String TAG = MainActivity.class.getSimpleName();//prints name of class without package name
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(isNetworkAvailable()) {
GetBlogPostsTask getBlogPostsTask = new GetBlogPostsTask(); // new thread
getBlogPostsTask.execute();// don't call do in background directly
}else{
Toast.makeText(this, "Network is unavailable", Toast.LENGTH_LONG).show();
}
}
public boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if(networkInfo != null && networkInfo.isConnected()){
isAvailable = true;
}
return isAvailable;
}
private void populateListView() {
ArrayAdapter<Post> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.postsListView);
list.setAdapter(adapter);
}
private class MyListAdapter extends ArrayAdapter<Post>{
public MyListAdapter() {
super(MainActivity.this, R.layout.item_view, myPosts);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// make sure we have a view to work with
View itemView = convertView;
if (itemView == null) {
itemView = getLayoutInflater().inflate(R.layout.item_view, parent,false);
}
//find the post to work with
Post currentPost = myPosts.get(position);
Context context = itemView.getContext();
String imageURL = currentPost.getImage();
if(imageURL == null || imageURL.isEmpty()){
ImageView imageView = (ImageView) itemView.findViewById(R.id.item_image);
imageView.setVisibility(View.GONE);
}else{
ImageView imageView = (ImageView) itemView.findViewById(R.id.item_image);
Picasso.with(context)
.load(imageURL)
.tag(context)
.placeholder(R.drawable.kanye8080s)
.error(R.drawable.stadiumarcadium)
.into(imageView);
imageView.setVisibility(View.VISIBLE);
}
//Username
TextView userText = (TextView) itemView.findViewById(R.id.item_txtUser);
userText.setText(currentPost.getUser());
//Time of post
TextView timeText = (TextView) itemView.findViewById(R.id.item_txtTime);
timeText.setText("" + currentPost.getTime());
//The actual post
TextView postText = (TextView) itemView.findViewById(R.id.item_txtPost);
postText.setText("" + currentPost.getPost());
//The actual post
TextView likesText = (TextView) itemView.findViewById(R.id.item_txtLikes);
likesText.setText("" + currentPost.getLikes());
return itemView;
}
}
private class GetBlogPostsTask extends AsyncTask<Object, Void, List> {
@Override
protected List doInBackground(Object[] params) {
int responseCode = -1;//need to have this variable outside scope of try/catch block
JSONObject jsonResponse = null;
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(""); /// api endpoint redacted
try {
HttpResponse response = client.execute(httpget);
StatusLine statusLine = response.getStatusLine();
responseCode = statusLine.getStatusCode();
if(responseCode == HttpURLConnection.HTTP_OK){ //could have used just 200 value
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while((line = reader.readLine()) != null){
builder.append(line);
}
jsonResponse = new JSONObject(builder.toString());
JSONArray jsonPosts = jsonResponse.getJSONArray("posts");
for(int i=0; i < jsonPosts.length(); i++){
JSONObject jsonPost = jsonPosts.getJSONObject(i);
int post_id = Integer.parseInt(jsonPost.getString("id"));
String post_user = jsonPost.getString("user");
String post_account = jsonPost.getString("account");
int post_time = Integer.parseInt(jsonPost.getString("time"));
String post_post = jsonPost.getString("post");
String post_image = jsonPost.getString("image");
int post_likes = Integer.parseInt(jsonPost.getString("likes"));
myPosts.add(new Post(post_id, post_user, post_account, post_time, post_post, post_image, "profile picture here", post_likes));
}
}else{
Log.i(TAG, "Unsuccessful HTTP Response Code: " + responseCode);
}
}
catch (MalformedURLException e){
Log.e(TAG, "Exception caught");
}
catch (IOException e){
Log.e(TAG, "Exception caught");
}
catch (Exception e){//must be in this order, this is the last, general catch
Log.e(TAG, "Exception caught", e);
}
return null;
}
@Override
protected void onPostExecute(List result) {
// call populateListView method here
populateListView();
super.onPostExecute(result);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
bất kỳ trợ giúp sẽ được đánh giá cao,
Cảm ơn bạn !!
EDIT:
Hi tất cả mọi người,
Tôi đã cập nhật mã của tôi vào một mô hình quan điểm chủ sở hữu, tạo ra hai quan điểm riêng biệt (một cho một bài đăng với một hình ảnh, một cho một bài đăng chỉ với văn bản) và cũng bao gồm scroll detection capabilities mới của Picasso.
Tôi đã thấy cải thiện trong một số hình ảnh tải nhanh hơn, ít nhất là khi chế độ xem được lấy nét trong khi cuộn, hình ảnh có nhiều khả năng tải ngay bây giờ. Tuy nhiên, khi cuộn lên những hình ảnh tương tự đã từng được tải, biến mất. Nó cảm thấy như Picasso chỉ tải 4-5 hình ảnh tại một thời điểm và thay thế những hình ảnh đã được nạp để nhường chỗ. Mã được cập nhật của tôi là bên dưới:
public class MainActivity extends Activity {
private List<Post> myPosts = new ArrayList<Post>();
protected String[] mBlogPostTitles;
public static final String TAG = MainActivity.class.getSimpleName();//prints name of class without package name
...
private void populateListView() {
Activity activity = MainActivity.this;
ArrayAdapter<Post> adapter = new MyListAdapter();
ListView list = (ListView) findViewById(R.id.postsListView);
list.setAdapter(adapter);
list.setOnScrollListener(new SampleScrollListener(activity));
}
private class MyListAdapter extends ArrayAdapter<Post>{
public MyListAdapter() {
super(MainActivity.this, R.layout.item_view, myPosts);
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
String imageURL = myPosts.get(position).getImage();
if(imageURL == null || imageURL.isEmpty()){
return 1; // text based
}else{
return 0; // image based
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
PostViewHolder holder;
int type = getItemViewType(position);
View itemView = convertView;
// make sure we have a view to work with
if (itemView == null) {
holder = new PostViewHolder();
if(type == 1) {
itemView = getLayoutInflater().inflate(R.layout.item_view, parent, false);
}else {
itemView = getLayoutInflater().inflate(R.layout.image_post_view, parent, false);
holder.image = (ImageView) itemView.findViewById(R.id.item_image);
}
holder.user = (TextView) itemView.findViewById(R.id.item_txtUser);
holder.time = (TextView) itemView.findViewById(R.id.item_txtTime);
holder.post = (TextView) itemView.findViewById(R.id.item_txtPost);
holder.likes = (TextView) itemView.findViewById(R.id.item_txtLikes);
itemView.setTag(holder);
} else {
holder = (PostViewHolder) itemView.getTag();
}
//find the post to work with
Post currentPost = myPosts.get(position);
if(type != 1) {
Context context = itemView.getContext();
String imageURL = currentPost.getImage();
Picasso.with(context).setIndicatorsEnabled(true);
//Picasso.with(context).setLoggingEnabled(true);
Picasso.with(context)
.load(imageURL)
.tag(context)
.placeholder(R.drawable.kanye8080s)
//.skipMemoryCache()
.error(R.drawable.stadiumarcadium)
.fit()
.into(holder.image);
}
//Username
holder.user.setText(currentPost.getUser());
//Time of post
holder.time.setText("" + currentPost.getTime());
//The actual post
holder.post.setText(currentPost.getPost());
//Likes for the post
holder.likes.setText("" + currentPost.getLikes());
return itemView;
}
}
public class SampleScrollListener implements AbsListView.OnScrollListener {
private final Context context;
public SampleScrollListener(Context context) {
this.context = context;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
final Picasso picasso = Picasso.with(context);
if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
picasso.resumeTag(context);
} else {
picasso.pauseTag(context);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
// Do nothing.
}
}
...
}
Sự cố đến từ đâu? Tôi có nên tải trước những hình ảnh này bằng cách nào đó trong bộ nhớ cache không? Trong khi tôi đã xem xét tính năng ưu tiên mới của Picasso, tôi có nên nói cho Picasso bằng cách nào đó để tải hình ảnh theo thứ tự xuất hiện trong listview của tôi không? Bất kỳ ý tưởng? Làm thế nào tôi có thể "giữ" hình ảnh đã được tải khi cuộn lên? Cảm ơn!
- 24x7
Theo mặc định, Picasso đã làm bộ nhớ đệm theo khuyến nghị của tài liệu dành cho nhà phát triển [ở đây] (http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html). Xem [câu trả lời này] (http://stackoverflow.com/a/20105828/2911458) để biết một số cuộc thảo luận về bộ nhớ cache được sử dụng. Nếu bạn muốn kiểm tra xem bộ nhớ đệm có đang hoạt động hay không, hãy kích hoạt chế độ gỡ lỗi của Picasso bằng cách gọi 'setIndicatorsEnabled (true)' trên thể hiện Picasso của bạn. Các chỉ số được mô tả [ở đây] (http://square.github.io/picasso/). – stkent
Tôi bật các chỉ số, nhưng không thể xác định được nhiều. Ngay cả với một số hình ảnh giảm (7) bên trong một listview với 10 mục vẫn còn hoạt động bất thường. Hình ảnh tải lại khi bạn cuộn lên và xuất hiện để tải chậm trừ khi chúng được tập trung vào listview. – 24x7
Tại sao bạn gọi setVisibility() trên imageView. Hãy thử nó mà không có điều đó. Sử dụng trình giữ chỗ và hình ảnh lỗi trong Picasso cho điều đó, điều này có thể là một phần của vấn đề. Bạn có thể. Load (null) với Picasso tôi tin. –