从Parse下载图像和文本并添加到ArrayList会产生意外结果吗?

时间:2016-07-17 13:26:59

标签: java android listview arraylist custom-adapter

我一直致力于从Parse下载缩略图和文本的应用程序,并将其添加到ArrayLists,然后通过ListView的自定义适配器显示。这里的问题是,所需内容的缩略图有时会放错位置。例如:在我的个人资料中,而不是我的图片将放置从解析下载的另一张图片。如何解决?

MainActivity.java(下载内容)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

 if (isParseInitialized == false) {

        Parse.initialize(new Parse.Configuration.Builder(this)
                        .applicationId("AppId")
                .clientKey("ClientKey")
                .server("https://parseapi.back4app.com")

                .build()
        );

        isParseInitialized = true;

    }

    catchVideos();

    progressBar = (ProgressBar) findViewById(R.id.progressBar);

    context = this;
    listView = (ListView) findViewById(R.id.listView);

    customAdapter = new CustomAdapter(MainActivity.this, titles, thumbnails, channel);

    //progressBar.setVisibility(View.INVISIBLE);

    final Handler handler = new Handler();
    Runnable run = new Runnable() {
        @Override
        public void run() {

            handler.postDelayed(this, 1000);

            if (tapped == true) {

                ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Content");
                query.whereEqualTo("Title", title);
                query.findInBackground(new FindCallback<ParseObject>() {
                    @Override
                    public void done(List<ParseObject> objects, ParseException e) {
                        if(e == null) {

                            for (ParseObject object : objects) {

                               Log.i("Info", object.getString("url"));

                                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(object.getString("url")));
                                startActivity(intent);
                            }
                        }
                    }
                });

                tapped = false;

            }
        }
    };

    handler.post(run);



}

public void catchVideos(){

    ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Content");
    query.whereNotEqualTo("Status", null);
    query.orderByDescending("createdAt");
    query.findInBackground(new FindCallback<ParseObject>() {
        @Override
        public void done(List<ParseObject> objects, ParseException e) {
            if(e == null) {

                if (!titles.isEmpty()) {
                    titles.clear();
                }

                if (!channel.isEmpty()) {
                    channel.clear();
                }

                if (!thumbnails.isEmpty()) {
                    thumbnails.clear();
                }

                for (ParseObject object : objects) {

                    titles.add(object.getString("Title"));
                    channel.add(object.getString("Channel"));

                    ParseFile file = (ParseFile) object.get("Thumbnail");
                    file.getDataInBackground(new GetDataCallback() {
                        @Override
                        public void done(byte[] data, ParseException e) {

                            if (e == null) {

                                Bitmap thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
                                thumbnails.add(thumbnail);

                                listView.setAdapter(customAdapter);

                                progressBar.setVisibility(View.INVISIBLE);

                            }

                        }
                    });

                    customAdapter.notifyDataSetChanged();

                    Log.i("Info", object.getString("Title"));
                    Log.i("Info", object.getString("url"));
                }

            }
        }
    });
}

CustomAdapter.java

        public class CustomAdapter extends BaseAdapter{

ArrayList<String> result;
ArrayList<String> channelName;
Context context;
ArrayList<Bitmap> imageId;
private static LayoutInflater inflater=null;
public CustomAdapter(MainActivity mainActivity, ArrayList<String> titles, ArrayList<Bitmap> thumbnails, ArrayList<String> channel) {
    // TODO Auto-generated constructor stub
    result=titles;
    channelName=channel;
    context=mainActivity;
    imageId=thumbnails;
    inflater = ( LayoutInflater )context.
            getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
    // TODO Auto-generated method stub
    return result.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

public class Holder
{
    TextView tv;
    TextView channelText;
    ImageView img;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Holder holder=new Holder();
    View rowView;
    rowView = inflater.inflate(R.layout.custom_row, null);
    holder.tv=(TextView) rowView.findViewById(R.id.textView1);
    holder.channelText = (TextView) rowView.findViewById(R.id.channel);
    holder.img=(ImageView) rowView.findViewById(R.id.imageView1);
    try  {
        holder.img.setImageBitmap(imageId.get(position));
    } catch (Exception e) {
        e.printStackTrace();
    }
    holder.tv.setText(result.get(position));
    holder.channelText.setText(channelName.get(position));

    rowView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //Toast.makeText(context, "You Clicked "+ result.get(position), Toast.LENGTH_LONG).show();
            //Launch URL
            MainActivity.tapped = true;
            MainActivity.title = result.get(position);

        }
    });

    return rowView;

    }

  }

1 个答案:

答案 0 :(得分:0)

下载后,您将每个图像添加到列表中。之后,您将按顺序迭代图像。但是,它们在列表中出现的顺序不一定与您请求它们的顺序相同。它们是异步加载的,这意味着代码不会等待图像完成加载,然后再转到下一个。如果您开始加载大图像,然后立即开始加载小图像,小图像可能会先完成下载。在结果列表中,小图像将出现在较大的图像之前,即使它是第二次请求。

要修复图片列表的顺序,您可以使用Futures。不要将thumbnails声明为List<Bitmap>,而是将其设为List<Future<Bitmap>>。然后,同时将所有三个项目添加到列表中。

    titles.add(object.getString("Title"));
    channel.add(object.getString("Channel"));
    CompletableFuture<Bitmap> futureThumbnail = new CompletableFuture<>();
    thumbnails.add(futureThumbnail);

无论图像下载多长时间,都可以保证所有三个列表的顺序相同。

下一步是用相应的图像填写每个未来。

    ParseFile file = (ParseFile) object.get("Thumbnail");
    file.getDataInBackground(new GetDataCallback() {
        @Override
        public void done(byte[] data, ParseException e) {
            if (e == null) {
                Bitmap thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
                future.complete(thumbnail);
                ...

此方法的另一个好处是您可以等待图像完成下载。等待所有图像下载并按正确顺序将它们放入列表中:

List<Bitmap> thumbnails = new ArrayList<>();
for (Future<Bitmap> future : futureThumbnails) {
    thumbnails.add(future.get());
}

或者,如果您不想等待:

List<Bitmap> thumbnails = new ArrayList<>();
Bitmap defaultValue = null; // or preferably some other default value
for (Future<Bitmap> future : futureThumbnails) {
    thumbnails.add(future.isDone() ? future.get() : defaultValue); 
}