7

私のアプリケーションでは、URLから多くの画像をダウンロードして、gridViewに表示する必要があります。(1〜200枚の写真の間である可能性があります)。すべての写真を一度にダウンロードしたくありません。怠惰なダウンロードについて読みましたが、質問は次のとおりです。Jsonの一部のみを取得し、別のスレッドで画像をダウンロードできます。ユーザーがgridViewを下にスクロールした場合にのみ、Jsonの他の部分に進みます。すぐ?

編集:こんにちは。このgridViewに複数選択を実装したいのですが、アダプターのgetView()メソッドにコードを実装するのに問題があります。これは私が使用している例です:example。getView()メソッドでこのコードを組み合わせるにはどうすればよいですか?

public View getView(int position, View convertView, ViewGroup parent) {
        CheckableLayout l;
        ImageView i;

        if (convertView == null) {
            i = new ImageView(Grid3.this);
            i.setScaleType(ImageView.ScaleType.FIT_CENTER);
            i.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
            l = new CheckableLayout(Grid3.this);
            l.setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT,
                    GridView.LayoutParams.WRAP_CONTENT));
            l.addView(i);
        } else {
            l = (CheckableLayout) convertView;
            i = (ImageView) l.getChildAt(0);
        }

        ResolveInfo info = mApps.get(position);
        i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));

        return l;
    }


public class CheckableLayout extends FrameLayout implements Checkable {
    private boolean mChecked;

    public CheckableLayout(Context context) {
        super(context);
    }

    public void setChecked(boolean checked) {
        mChecked = checked;
        setBackgroundDrawable(checked ?
                getResources().getDrawable(R.drawable.blue)
                : null);
    }

    public boolean isChecked() {
        return mChecked;
    }

    public void toggle() {
        setChecked(!mChecked);
    }

}

私のgetView()コード:

public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    ViewHolder holder;
    View vi = convertView;

    if(convertView == null) {
        vi = inflater.inflate(com.egedsoft.instaprint.R.layout.item_clickable, null);
        holder = new ViewHolder();
        holder.imgPhoto = (ImageView)vi.findViewById(com.egedsoft.instaprint.R.id.imageClickable);
        vi.setTag(holder);

    } else {
        holder = (ViewHolder) vi.getTag();
    }


    if (!arrayUrls.get(position).getThumbnailUrl().isEmpty()){
        imageLoader.DisplayImage(arrayUrls.get(position).getThumbnailUrl(), holder.imgPhoto);
    }


    return vi;
}
4

4 に答える 4

37

これが私のアクティビティで複数の写真を取得する方法です。ロジックに合わせてその一部を使用できます。これを使用して、アルバムからFacebook画像を取得します。ですから、私のニーズは(私が想定している)あなたのニーズとは異なります。しかし、繰り返しになりますが、ロジックはあなたに役立つかもしれません。

注:これは長くなります。;-)

これらは、ACtivityを介して使用するためのグローバル宣言です。

// HOLD THE URL TO MAKE THE API CALL TO
private String URL;

// STORE THE PAGING URL
private String pagingURL;

// FLAG FOR CURRENT PAGE
int current_page = 1;

// BOOLEAN TO CHECK IF NEW FEEDS ARE LOADING
Boolean loadingMore = true;

Boolean stopLoadingData = false;

これは、画像の初期セットをフェッチするコードブロックです。

private class getPhotosData extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... arg0) {

        // CHANGE THE LOADING MORE STATUS TO PREVENT DUPLICATE CALLS FOR
        // MORE DATA WHILE LOADING A BATCH
        loadingMore = true;

        // SET THE INITIAL URL TO GET THE FIRST LOT OF ALBUMS
        URL = "https://graph.facebook.com/" + initialAlbumID
                + "/photos&access_token="
                + Utility.mFacebook.getAccessToken() + "?limit=10";

        try {

            HttpClient hc = new DefaultHttpClient();
            HttpGet get = new HttpGet(URL);
            HttpResponse rp = hc.execute(get);

            if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String queryAlbums = EntityUtils.toString(rp.getEntity());

                JSONObject JOTemp = new JSONObject(queryAlbums);

                JSONArray JAPhotos = JOTemp.getJSONArray("data");

                // IN MY CODE, I GET THE NEXT PAGE LINK HERE

                getPhotos photos;

                for (int i = 0; i < JAPhotos.length(); i++) {
                    JSONObject JOPhotos = JAPhotos.getJSONObject(i);
                    // Log.e("INDIVIDUAL ALBUMS", JOPhotos.toString());

                    if (JOPhotos.has("link")) {

                        photos = new getPhotos();

                        // GET THE ALBUM ID
                        if (JOPhotos.has("id")) {
                            photos.setPhotoID(JOPhotos.getString("id"));
                        } else {
                            photos.setPhotoID(null);
                        }

                        // GET THE ALBUM NAME
                        if (JOPhotos.has("name")) {
                            photos.setPhotoName(JOPhotos.getString("name"));
                        } else {
                            photos.setPhotoName(null);
                        }

                        // GET THE ALBUM COVER PHOTO
                        if (JOPhotos.has("picture")) {
                            photos.setPhotoPicture(JOPhotos
                                    .getString("picture"));
                        } else {
                            photos.setPhotoPicture(null);
                        }

                        // GET THE PHOTO'S SOURCE
                        if (JOPhotos.has("source")) {
                            photos.setPhotoSource(JOPhotos
                                    .getString("source"));
                        } else {
                            photos.setPhotoSource(null);
                        }

                        arrPhotos.add(photos);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {

        // SET THE ADAPTER TO THE GRIDVIEW
        gridOfPhotos.setAdapter(adapter);

        // CHANGE THE LOADING MORE STATUS
        loadingMore = false;
    }

}

これは、ユーザーが最後までスクロールしたことを検出し、新しい画像のセットをフェッチするためのものです。

// ONSCROLLLISTENER
gridOfPhotos.setOnScrollListener(new OnScrollListener() {

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        int lastInScreen = firstVisibleItem + visibleItemCount;
        if ((lastInScreen == totalItemCount) && !(loadingMore)) {

            if (stopLoadingData == false) {
                // FETCH THE NEXT BATCH OF FEEDS
                new loadMorePhotos().execute();
            }

        }
    }
});

そして最後に、これが次の画像セットを取得する方法です。

private class loadMorePhotos extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... arg0) {

        // SET LOADING MORE "TRUE"
        loadingMore = true;

        // INCREMENT CURRENT PAGE
        current_page += 1;

        // Next page request
        URL = pagingURL;

        try {

            HttpClient hc = new DefaultHttpClient();
            HttpGet get = new HttpGet(URL);
            HttpResponse rp = hc.execute(get);

            if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String queryAlbums = EntityUtils.toString(rp.getEntity());
                // Log.e("PAGED RESULT", queryAlbums);

                JSONObject JOTemp = new JSONObject(queryAlbums);

                JSONArray JAPhotos = JOTemp.getJSONArray("data");

                // IN MY CODE, I GET THE NEXT PAGE LINK HERE

                getPhotos photos;

                for (int i = 0; i < JAPhotos.length(); i++) {
                    JSONObject JOPhotos = JAPhotos.getJSONObject(i);
                    // Log.e("INDIVIDUAL ALBUMS", JOPhotos.toString());

                    if (JOPhotos.has("link")) {

                        photos = new getPhotos();

                        // GET THE ALBUM ID
                        if (JOPhotos.has("id")) {
                            photos.setPhotoID(JOPhotos.getString("id"));
                        } else {
                            photos.setPhotoID(null);
                        }

                        // GET THE ALBUM NAME
                        if (JOPhotos.has("name")) {
                            photos.setPhotoName(JOPhotos.getString("name"));
                        } else {
                            photos.setPhotoName(null);
                        }

                        // GET THE ALBUM COVER PHOTO
                        if (JOPhotos.has("picture")) {
                            photos.setPhotoPicture(JOPhotos
                                    .getString("picture"));
                        } else {
                            photos.setPhotoPicture(null);
                        }

                        // GET THE ALBUM'S PHOTO COUNT
                        if (JOPhotos.has("source")) {
                            photos.setPhotoSource(JOPhotos
                                    .getString("source"));
                        } else {
                            photos.setPhotoSource(null);
                        }

                        arrPhotos.add(photos);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {

        // get listview current position - used to maintain scroll position
        int currentPosition = gridOfPhotos.getFirstVisiblePosition();

        // APPEND NEW DATA TO THE ARRAYLIST AND SET THE ADAPTER TO THE
        // LISTVIEW
        adapter = new PhotosAdapter(Photos.this, arrPhotos);
        gridOfPhotos.setAdapter(adapter);

        // Setting new scroll position
        gridOfPhotos.setSelection(currentPosition + 1);

        // SET LOADINGMORE "FALSE" AFTER ADDING NEW FEEDS TO THE EXISTING
        // LIST
        loadingMore = false;
    }

}

そして、これはヘルパークラスでSETありGET、上記のクエリから収集されたデータです。

public class getPhotos {

    String PhotoID;

    String PhotoName;

    String PhotoPicture;

    String PhotoSource;

    // SET THE PHOTO ID
    public void setPhotoID(String PhotoID)  {
        this.PhotoID = PhotoID;
    }

    // GET THE PHOTO ID
    public String getPhotoID()  {
        return PhotoID;
    }

    // SET THE PHOTO NAME
    public void setPhotoName(String PhotoName)  {
        this.PhotoName = PhotoName;
    }

    // GET THE PHOTO NAME
    public String getPhotoName()    {
        return PhotoName;
    }

    // SET THE PHOTO PICTURE
    public void setPhotoPicture(String PhotoPicture)    {
        this.PhotoPicture = PhotoPicture;
    }

    // GET THE PHOTO PICTURE
    public String getPhotoPicture() {
        return PhotoPicture;
    }

    // SET THE PHOTO SOURCE
    public void setPhotoSource(String PhotoSource)  {
        this.PhotoSource = PhotoSource;
    }

    // GET THE PHOTO SOURCE
    public String getPhotoSource()  {
        return PhotoSource;
    }
}

コードも必要な場合はadapter、お知らせください。アダプターでFedorの LazyLoadingメソッドを使用します。

ふぅ。これがお役に立てば幸いです。ご不明な点がございましたら、お気軽にお問い合わせください。:-)

編集:追加されたアダプタコード:

public class PhotosAdapter extends BaseAdapter {

    private Activity activity;

    ArrayList<getPhotos> arrayPhotos;

    private static LayoutInflater inflater = null;
    ImageLoader imageLoader; 

    public PhotosAdapter(Activity a, ArrayList<getPhotos> arrPhotos) {

        activity = a;

        arrayPhotos = arrPhotos;

        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return arrayPhotos.size();
    }

    public Object getItem(int position) {
        return arrayPhotos.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        ViewHolder holder;

        View vi = convertView;
        if(convertView == null) {
            vi = inflater.inflate(R.layout.photos_item, null);

            holder = new ViewHolder();

            holder.imgPhoto = (ImageView)vi.findViewById(R.id.grid_item_image);

            vi.setTag(holder);
          } else {
            holder = (ViewHolder) vi.getTag();
        }


        if (arrayPhotos.get(position).getPhotoPicture() != null){
            imageLoader.DisplayImage(arrayPhotos.get(position).getPhotoPicture(), holder.imgPhoto);
        }
        return vi;
    }

    static class ViewHolder {
        ImageView imgPhoto;

    }
}

編集:ロード中に進行状況を表示する手順を追加しました:

そのすぐ下にGridViewがあるXMLにProgressBarを追加します。問題が発生した場合は、ウェイトをいじってみてください。

<LinearLayout
    android:id="@+id/linlaProgressBar"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal" >

    <ProgressBar
        style="@style/Spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="2dp" />
</LinearLayout>

Javaで、Linearlayout linlaProgressBarをグローバルとして宣言し、にキャストして、onCreate()可視性を次のように設定します。linlaProgressBar.setVisibility(View.GONE);

そして、次のonPreExecute()ように使用します。

@Override
protected void onPreExecute() {
    // SHOW THE BOTTOM PROGRESS BAR (SPINNER) WHILE LOADING MORE PHOTOS
    linlaProgressBar.setVisibility(View.VISIBLE);
}

そして最後に、これをonPostExecute()

// HIDE THE BOTTOM PROGRESS BAR (SPINNER) AFTER LOADING MORE ALBUMS
linlaProgressBar.setVisibility(View.GONE);
于 2012-11-07T08:29:53.323 に答える
4

AndroidドキュメントのアダプタビューGridViewの使用をご覧ください。最も重要なことは、アダプタがメソッドを呼び出して、getView画面に表示されているエントリの位置のみを渡し、ユーザーがスクロールしたときに別の位置を要求することです。

簡単な方法は、 AsyncTaskgetViewを使用してアダプタのメソッドに必要なイメージをダウンロードすることです。

があります

于 2012-11-07T08:12:33.917 に答える
0

経験から言えば、メモリを合理的に消費しながらスムーズなスクロール(および全体的な応答性)を実現するのは難しいことです。

最初に既存のソリューションを探すことをお勧めします。たとえば、ここから始めます 。ListViewでの画像の遅延読み込み

最終的には、カスタムの独自のソリューションになりました。これは、ダウンロードリクエストをキューに入れ、外部ストレージにダウンロードしてキャッシュし、まだ表示されている画像のみをキャッシュするバックグラウンドスレッドです。新しいイメージが到着すると、ビューに通知が届き、アダプターに更新を通知するタイミングが決定されます。

また、場合によっては重要だった帯域幅も節約できます。

于 2012-11-07T08:31:54.847 に答える
0

IceMANの答えは非常に便利だと思いましたが、2つのAsyncTaskを使用しないことをお勧めします。これは、簡単に作成できます。

必要なデータをフェッチするためのユニバーサルメソッドを作成する必要があります。ここで、if / else条件を作成できます(例として)。

        movies = fetchMovie.execute(sort).get();
        if (movies == null) {
            movieList = new ArrayList<>();
        } else if (addMovies) {
            movieList.addAll(movies);
        } else {
            movieList = movies;
        }

addMoviesは、onScrollメソッドのブール値です。AsyncTaskで、クエリURLと出来上がりで現在のページを提供します-コードを小さくしました:)

于 2015-12-17T05:10:31.007 に答える