我的列表视图显示两次项目

时间:2015-07-18 19:42:36

标签: java android rest android-listview spotify

我的Listview似乎两次显示我的列表项目,对于我的生活,我无法找到问题所在。我已经用推荐的 artistsAlbum.clear()(artistsAlbum是一个ArrayList)替换了我的代码中的语句。我甚至用“ artistsAlbum = new ArrayList()”这句话取代了artistAlbum.clear(),但它有效,但由于显而易见的原因,我不相信这是一个解决方案,因为我每次重新显示Listview时都会创建更多引用。 任何人都可以提供帮助。

MainActivity:

package com.example.richard.webapitest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;

import com.example.richard.webapitest.model.ArtistsAlbum;
import com.example.richard.webapitest.service.APIService;

import java.util.ArrayList;

import kaaes.spotify.webapi.android.models.ArtistsPager;
import kaaes.spotify.webapi.android.models.Image;
import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;


public class MainActivity extends ActionBarActivity {
    public final static String EXTRA_MESSAGE = "com.example.richard.webapitest.MESSAGE";
    public final static String EXTRA_ARTIST = "com.example.richard.webapitest.NAME";
    public final static int MY_CHILD_ACTIVITY = 0;
    static final  String LOG_TAG = MainActivity.class.getSimpleName();
    static final String END_POINT = "https://api.spotify.com/v1";
     final String[] Url = new String[1];
    static ArrayList<ArtistsAlbum> artistsAlbums;
    ArrayList<ArtistsAlbum> testAlbums;
    ArtistsAlbum album;

    String url;
    String name;
    String id;

    String mUrl;
    String mName;
    String mId;
    int count;
    APIService service;

    ListView mListView;
    AlbumsAdapter mAdapter;

    boolean listViewRefresh = false;

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString(EXTRA_ARTIST,name);
        super.onSaveInstanceState(outState);
    }

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

        if( savedInstanceState != null ) {
            name = savedInstanceState .getString(EXTRA_ARTIST);
        }

        artistsAlbums = new ArrayList<ArtistsAlbum>();

        final RestAdapter adapter = new RestAdapter.Builder()
                .setEndpoint(END_POINT)
                .build();
        service = adapter.create(APIService.class);

        EditText tview = (EditText) findViewById(R.id.artist_field);
        tview.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                                          int after) {

                Log.v("LOG_TAG", s + " onTextChanged() " + " start: " + start + " count: " + count + " after: " + after);
                listViewRefresh = (start == 0) && (count == 1) && (after == 0);
            }

            @Override

            public void afterTextChanged(Editable s) { //aftertextchanged{
                Log.v("LOG_TAG", s + " afterTextChanged()");

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

                name = s.toString();
                Log.v("LOG_TAG", s.length() + " onTextChanged() " + " start: " + start + " before: " + before + " count:" + count);
                if ((start == 0) && (before == 1) && (count == 0)) { //if .. 7
                    if (mAdapter != null) {
                        mAdapter.clear();
                        mAdapter.notifyDataSetChanged();
                    }
                } else {
                    //======================================A R T I S T S=====================================m============
                    service.searchArtists(name, new Callback<ArtistsPager>() {
                        @Override
                        public void success(ArtistsPager artistsPager, Response response) {
                            Image image;
                            if (artistsPager.artists.items != null) {//for .. 6
                                if (mAdapter != null) {
                                    mAdapter.clear();
                                    mAdapter.notifyDataSetChanged();
                                }
                                artistsAlbums.clear();
                                for (int i = 0; i < artistsPager.artists.items.size(); i++) { //for .. 1
                                        try {  // try .. 1
                                            mName = artistsPager.artists.items.get(i).name;         //Breakpoint here!!
                                            mId = artistsPager.artists.items.get(i).id;
                                            int size = artistsPager.artists.items.get(i).images.size();

                                            if (size == 0) {
                                                //------------------------------------------
                                                album = new ArtistsAlbum();
                                                album.setName(mName);
                                                album.setId(mId);
                                                artistsAlbums.add(i,album);
                                                //------------------------------------------
                                            } else {
                                                for (int j = 0; j < size; j++) {
                                                    if (80 > artistsPager.artists.items.get(i).images.get(j).width) {
                                                        mUrl = artistsPager.artists.items.get(i).images.get(j).url;
                                                        album = new ArtistsAlbum();
                                                        album.setUrl(mUrl);
                                                        album.setName(mName);
                                                        album.setId(mId);
                                                        artistsAlbums.add(i,album);
                                                    }
                                                }
                                            }
                                        } catch (IndexOutOfBoundsException e) { //try .. 1
                                            e.printStackTrace();
                                        }
                                    }// for .. 1
                                     displayItems();


                                mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                                        @Override
                                        public void onItemClick(final AdapterView<?> parent, final View view,
                                                                int position, long id) {
                                            final ArtistsAlbum item = (ArtistsAlbum) parent.getItemAtPosition(position);
                                            // System.out.println("LOG_TAG" + "name: " + item.getName() + " id: " + item.getId() + " Url: " + item.getUrl());
                                            sendMessage(item.getId());
                                        }
                                    });
                                    Log.v(LOG_TAG,"=======================================================================================");
                                    for (ArtistsAlbum obj : artistsAlbums)
                                        System.out.println("LOG_TAG" + "name: " + obj.getName() + " id: " + obj.getId() + " Url: " + obj.getUrl());
                                    Log.v(LOG_TAG, "=======================================================================================");

                                } //for..6
                            }

                            @Override
                            public void failure (RetrofitError error){

                            }
                        }

                        );
                    }//if .. 7

                } //aftertextchanged
            });

}
    public void sendMessage(String message) {
        Intent intent = new Intent(this, DetailActivity.class);
        intent.putExtra(EXTRA_MESSAGE, message);
        startActivityForResult(intent, MY_CHILD_ACTIVITY);
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) {
            case (MY_CHILD_ACTIVITY) : {
                if (resultCode == Activity.RESULT_OK) {
                    // TODO Extract the data returned from the child Activity.
                }
                break;
            }
        }
    }

    private void displayItems() {
        //Use FlowerAdapter to display data
        if (mAdapter == null) {
            Log.v(LOG_TAG,"in displayItems" + count++);
            mAdapter = new AlbumsAdapter(getBaseContext(), R.layout.item_flower, artistsAlbums);
            mListView = (ListView) findViewById(android.R.id.list);
            mListView.setAdapter(mAdapter);
        } else {
            mAdapter.addAll(artistsAlbums);
            mAdapter.notifyDataSetChanged();

        }
    }

    @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);
    }
}

AlbumsAdapter:

package com.example.richard.webapitest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.richard.webapitest.model.ArtistsAlbum;

import java.io.InputStream;
import java.net.URL;
import java.util.List;

public class AlbumsAdapter extends ArrayAdapter<ArtistsAlbum> {
    private Context context;
    private List<ArtistsAlbum> albumsList;

    private LruCache<String, Bitmap> imageCache;
    public AlbumsAdapter(Context context, int resource, List<ArtistsAlbum> objects) {
        super(context, resource, objects);
        this.context = context;
        this.albumsList = objects;

        final int maxMemory = (int)(Runtime.getRuntime().maxMemory() /1024);
        final int cacheSize = maxMemory / 8;
        imageCache = new LruCache<>(cacheSize);
    }

    @Override
    public int getCount() {
        return albumsList.size();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater =
                (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.item_flower, parent, false);

        //Display album name in the TextView widget
        ArtistsAlbum album = albumsList.get(position);
        TextView tv = (TextView) view.findViewById(R.id.textView1);
        tv.setText(album.getName());

        //Display album image in ImageView widget
        Bitmap bitmap = imageCache.get(album.getId());
        if (bitmap != null) {
            ImageView image = (ImageView) view.findViewById(R.id.imageView1);
            //image.setImageBitmap(album.getBitmap());
            image.setImageBitmap(bitmap);

        }
        else {
            AlbumAndView container = new AlbumAndView();
            container.album = album;
            container.view = view;

            ImageLoader loader = new ImageLoader();
            loader.execute(container);
        }

        return view;
    }

    class AlbumAndView {
        public ArtistsAlbum album;      //ArtistAlbum class
        public View view;
        public Bitmap bitmap;
    }

    private class ImageLoader extends AsyncTask<AlbumAndView, Void, AlbumAndView> {
        @Override
        protected AlbumAndView doInBackground(AlbumAndView... params) {

            AlbumAndView container = params[0];
            ArtistsAlbum album = container.album;

            try {
                //String imageUrl = MainActivity.PHOTOS_BASE_URL + album.getPhoto();
                String imageUrl = album.getUrl();


                if (null!=imageUrl) {
                    //Log.v("LOG_TAG", "image: " + imageUrl);
                    InputStream in = (InputStream) new URL(imageUrl).getContent();
                    Bitmap bitmap = BitmapFactory.decodeStream(in);
                    //Log.v("LOG_TAG", "bitmap size: "+bitmap.getByteCount());
                    // album.setBitmap(bitmap);             //WHAT DOES THIS LINE DO?

                    in.close();
                    container.bitmap = bitmap;
                } else {
                    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.record_icon);
                    container.bitmap = bitmap;
                }
                return container;

            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(AlbumAndView result) {
            ImageView image = (ImageView) result.view.findViewById(R.id.imageView1);
            //Log.v("LOG_TAG", "image: " + image);
            if (null!=result.bitmap) {
                image.setImageBitmap(result.bitmap);
                imageCache.put(result.album.getId(), result.bitmap);
            }
        }

    }

}

ArtistsAlbum(模特):

package com.example.richard.webapitest.model;

import android.graphics.Bitmap;

/**
 * Created by richard on 25/06/15.
 */
public class ArtistsAlbum {
    private String name;                        //Name of album.
    private String id;                          //Id - used later to get the top 10 items and
                                                //used as a key to store/retrieve the bitmap image in cache.

    private String url;                         //url of thumb nail.
    public Bitmap bitmap;                      //The bitmap of the thumb nail.

    public String getId(){ return id;}
    public void setId(String id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name){this.name = name;}
    public String getUrl() {return url;}
    public void setUrl(String url) {this.url = url;}
    public void setBitmap(Bitmap bitmap) {this.bitmap = bitmap;}
    public Bitmap getBitmap() { return bitmap;}
}

APIService(Spotify服务):

package com.example.richard.webapitest.service;

import kaaes.spotify.webapi.android.models.Albums;
import kaaes.spotify.webapi.android.models.AlbumsPager;
import kaaes.spotify.webapi.android.models.Artist;
import kaaes.spotify.webapi.android.models.Artists;
import kaaes.spotify.webapi.android.models.ArtistsPager;
import kaaes.spotify.webapi.android.models.Tracks;
import kaaes.spotify.webapi.android.models.TracksPager;
import retrofit.Callback;
import retrofit.http.GET;
import retrofit.http.Path;
import retrofit.http.Query;

public interface APIService {

    /**
     * The maximum number of objects to return..
     */
    public static final String LIMIT = "limit";

    /**
     * The index of the first playlist to return. Default: 0 (the first object).
     * Use with limit to get the next set of objects (albums, playlists, etc).
     */
    public static final String OFFSET = "offset";

    /**
     * A comma-separated list of keywords that will be used to filter the response.
     * Valid values are: {@code album}, {@code single}, {@code appears_on}, {@code compilation}
     */
    public static final String ALBUM_TYPE = "album_type";

    /**
     * The country: an ISO 3166-1 alpha-2 country code.
     * Limit the response to one particular geographical market.
     * Synonym to {@link #COUNTRY}
     */
    public static final String MARKET = "market";

    /**
     * Same as {@link #MARKET}
     */
    public static final String COUNTRY = "country";

    /**
     * The desired language, consisting of a lowercase ISO 639 language code
     * * and an uppercase ISO 3166-1 alpha-2 country code, joined by an underscore.
     * For example: es_MX, meaning "Spanish (Mexico)".
     */
    public static final String LOCALE = "locale";

    /************
     * Profiles *
     ************/
    /**
     * Get Spotify catalog information about albums that match a keyword string.
     *
     * @param q        The search query's keywords (and optional field filters and operators), for example "roadhouse+blues"
     * @param callback Callback method.
     * @see <a href="https://developer.spotify.com/web-api/search-item/">Search for an Item</a>
     */
    @GET("/search?type=album")
    public void searchAlbums(@Query("q") String q, Callback<AlbumsPager> callback);

    /**
     * Get Spotify catalog information about artists that match a keyword string.
     *
     * @param q        The search query's keywords (and optional field filters and operators), for example "roadhouse+blues"
     * @param callback Callback method.
     * @see <a href="https://developer.spotify.com/web-api/search-item/">Search for an Item</a>
     */
    @GET("/search?type=artist")
    public void searchArtists(@Query("q") String q, Callback<ArtistsPager> callback);

    /**
     * Get Spotify catalog information for several artists based on their Spotify IDs.
     *
     * @param artistIds A comma-separated list of the Spotify IDs for the artists
     * @param callback  Callback method
     * @see <a href="https://developer.spotify.com/web-api/get-several-artists/">Get Several Artists</a>
     */
    @GET("/artists")
    public void getArtists(@Query("ids") String artistIds, Callback<Artists> callback);

    /**
     * Get Spotify catalog information for a single artist identified by their unique Spotify ID.
     *
     * @param artistId The Spotify ID for the artist.
     * @see <a href="https://developer.spotify.com/web-api/get-artist/">Get an Artist</a>
     */
    @GET("/artists/{id}")
    public Artist getArtist(@Path("id") String artistId);

    /**
     * Get Spotify catalog information about tracks that match a keyword string.
     *
     * @param q        The search query's keywords (and optional field filters and operators), for example "roadhouse+blues"
     * @param callback Callback method.
     * @see <a href="https://developer.spotify.com/web-api/search-item/">Search for an Item</a>
     */
    @GET("/search?type=track")
    public void searchTracks(@Query("q") String q, Callback<TracksPager> callback);

    /**
     * Get Spotify catalog information for multiple albums identified by their Spotify IDs.
     *
     * @param albumIds A comma-separated list of the Spotify IDs for the albums
     * @param callback Callback method
     * @see <a href="https://developer.spotify.com/web-api/get-several-albums/">Get Several Albums</a>
     */
    @GET("/albums")
    public void getAlbums(@Query("ids") String albumIds, Callback<Albums> callback);

    /**
     * Get Spotify catalog information about an artist’s top tracks by country.
     *
     * @param artistId The Spotify ID for the artist.
     * @param callback Callback method
     * @see <a href="https://developer.spotify.com/web-api/get-artists-top-tracks/">Get an Artist’s Top Tracks</a>
     */
    @GET("/artists/{id}/top-tracks?country=US")
    public void getArtistTopTrack(@Path("id") String artistId, Callback<Tracks> callback);



}

1 个答案:

答案 0 :(得分:0)

我敢打赌,这个问题在某种程度上,你是如何将新值传递给适配器的。这,我要做的是在你的适配器类中创建这种方法:

public class setData(List<ArtistsAlbum> albumsList) {
        this.albumsList.clear();
        this.albumsList.addAll(albumsList);
        notifyDataSetChanged();
    }

然后在MainAvtivity中我会将displayItems()中的其他部分替换为:

} else {
            mAdapter.setData(artistsAlbums);
}

现在,为什么会这样发生。我们必须记住,它是异步发生的,在进行调用之前,并且执行请求有一些时间+事情可以并行完成,所以即使你正在进行一些清算,它们也不会被应用。