简体   繁体   中英

RecyclerView shows the same items

I am trying to implement RecyclerView, showing the data from JSONArray. Parsing works perfect, but RecyclerView shows in every item the information that must be only in the last item. There is the screenshot to make it clear.

Here is my code:

MainActivity.java

public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;

protected void onCreate(Bundle savedInstanceState) {
    setTheme(R.style.AppTheme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
    new parseTask().execute();
}

private class parseTask extends AsyncTask<Void, Void, String> {

    HttpURLConnection urlConnection = null;
    BufferedReader reader = null;
    String resultJson = "";
    ProgressDialog pdLoading = new ProgressDialog(MainActivity.this, R.style.MyDialogStyle);

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pdLoading.setMessage("\tLoading...");
        pdLoading.setCancelable(false);
        pdLoading.show();
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            URL url = new URL("http://songo.eu.pn/db_GetFromSongs.php");
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();
            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }

            resultJson = buffer.toString();

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

    @Override
    protected void onPostExecute(String strJson) {
        super.onPostExecute(strJson);
        List<DataSongs> data = new ArrayList<>();
        JSONObject dataJsonObj = null;

        try {
            dataJsonObj = new JSONObject(strJson);
            JSONArray songs = dataJsonObj.getJSONArray("Songs");
            DataSongs songData = new DataSongs();
            for (int i = 0; i < songs.length(); i++) {
                JSONObject song = songs.getJSONObject(i);
                songData.songName = song.getString("song");
                songData.songGenreID = song.getString("GenreID");
                songData.songUserID = song.getString("UserID");
                data.add(songData);
                Log.e("songo", "SongName: " + data.get(i).songName);
            }

            mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
            mAdapter = new RecyclerAdapter(MainActivity.this, data, mRecyclerView);
            mRecyclerView.setHasFixedSize(true);
            mLayoutManager = new LinearLayoutManager(MainActivity.this);
            mRecyclerView.setAdapter(mAdapter);
            mRecyclerView.setLayoutManager(mLayoutManager);

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

        pdLoading.dismiss();
    }
}

RecyclerAdapter.java

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

private Context context;
private LayoutInflater inflater;
List<DataSongs> data = Collections.emptyList();

public RecyclerAdapter(Context context, List<DataSongs> data, RecyclerView recyclerView) {
    this.context = context;
    inflater = LayoutInflater.from(context);
    this.data = data;
    this.recyclerView = recyclerView;
}

class ViewHolder extends RecyclerView.ViewHolder{

    TextView tv_songName;
    TextView tv_songGenreID;
    TextView tv_songUserID;

    public ViewHolder(View itemView) {
        super(itemView);
        tv_songName = (TextView) itemView.findViewById(R.id.tv_songName);
        tv_songGenreID = (TextView) itemView.findViewById(R.id.tv_songGenreID);
        tv_songUserID = (TextView) itemView.findViewById(R.id.tv_songUserID);
    }
}

// Создает новые views (вызывается layout manager-ом)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v=inflater.inflate(R.layout.recycler_item, parent,false);
    return new ViewHolder(v);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    DataSongs current = data.get(position);
    holder.tv_songName.setText(current.songName);
    holder.tv_songGenreID.setText(current.songGenreID);
    holder.tv_songUserID.setText(current.songUserID);
    Log.e("songo", "SongName: " + data.get(position).songName);        
}

@Override
public int getItemCount() {
    return data.size();
}

Log from MainActivity shows information as it should be (no equal lines).

Log from RecyclerAdapter shows that every songName is the same.

You are overriding the same DataSongs instance every iteration.

        DataSongs songData = new DataSongs();
        for (int i = 0; i < songs.length(); i++) {
            JSONObject song = songs.getJSONObject(i);
            songData.songName = song.getString("song");
            songData.songGenreID = song.getString("GenreID");
            songData.songUserID = song.getString("UserID");
            data.add(songData);
            Log.e("songo", "SongName: " + data.get(i).songName);
        }

Note that the new keyword is only called once.
The resulting list will contain the same object multiple times, and it's attributes are set to the last song in the list.

Simply move the creation of songData inside of the loop

        for (int i = 0; i < songs.length(); i++) {
            JSONObject song = songs.getJSONObject(i);

            DataSongs songData = new DataSongs();
            songData.songName = song.getString("song");
            songData.songGenreID = song.getString("GenreID");
            songData.songUserID = song.getString("UserID");
            data.add(songData);
            Log.e("songo", "SongName: " + data.get(i).songName);
        }
        dataJsonObj = new JSONObject(strJson);
        JSONArray songs = dataJsonObj.getJSONArray("Songs");
        DataSongs songData = new DataSongs();
        for (int i = 0; i < songs.length(); i++) {
            JSONObject song = songs.getJSONObject(i);
            songData.songName = song.getString("song");
            songData.songGenreID = song.getString("GenreID");
            songData.songUserID = song.getString("UserID");
            data.add(songData);
            Log.e("songo", "SongName: " + data.get(i).songName);
        }

The problem is not in RecyclerView related, it's in creating object .DataSongs object has been created only once , you have to create it every time you receive data from JSON array.So,create it inside for loop :

        dataJsonObj = new JSONObject(strJson);
        JSONArray songs = dataJsonObj.getJSONArray("Songs");

        for (int i = 0; i < songs.length(); i++) {
            JSONObject song = songs.getJSONObject(i);
            DataSongs songData = new DataSongs();
            songData.songName = song.getString("song");
            songData.songGenreID = song.getString("GenreID");
            songData.songUserID = song.getString("UserID");
            data.add(songData);
            Log.e("songo", "SongName: " + data.get(i).songName);
        }
DataSongs songData = new DataSongs(); 

for循环中的这一行代码每次都需要创建一个新的json对象来解决此问题

Try this

 try {
        dataJsonObj = new JSONObject(strJson);
        JSONArray songs = dataJsonObj.getJSONArray("Songs");
        DataSongs songData = null;
        for (int i = 0; i < songs.length(); i++) {
            songData = new DataSongs();
            JSONObject song = songs.getJSONObject(i);
            songData.songName = song.getString("song");
            songData.songGenreID = song.getString("GenreID");
            songData.songUserID = song.getString("UserID");
            data.add(songData);
            Log.e("songo", "SongName: " + data.get(i).songName);
        }

        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        mAdapter = new RecyclerAdapter(MainActivity.this, data, mRecyclerView);
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(MainActivity.this);
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(mLayoutManager);

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

You were creating the object outside the loop, as a result, there was only one object created

public class MainActivity extends AppCompatActivity {
        RecyclerView mRecyclerView;
        private RecyclerView.Adapter mAdapter;
        private RecyclerView.LayoutManager mLayoutManager;

        protected void onCreate(Bundle savedInstanceState) {
            setTheme(R.style.AppTheme);
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main_layout);
            new parseTask().execute();
        }

        private class parseTask extends AsyncTask<Void, Void, String> {

            HttpURLConnection urlConnection = null;
            BufferedReader reader = null;
            String resultJson = "";
            ProgressDialog pdLoading = new ProgressDialog(MainActivity.this, R.style.MyDialogStyle);

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                pdLoading.setMessage("\tLoading...");
                pdLoading.setCancelable(false);
                pdLoading.show();
            }

            @Override
            protected String doInBackground(Void... params) {
                try {
                    URL url = new URL("http://songo.eu.pn/db_GetFromSongs.php");
                    urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    urlConnection.connect();
                    InputStream inputStream = urlConnection.getInputStream();
                    StringBuffer buffer = new StringBuffer();
                    reader = new BufferedReader(new InputStreamReader(inputStream));

                    String line;
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line);
                    }

                    resultJson = buffer.toString();

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

            @Override
            protected void onPostExecute(String strJson) {
                super.onPostExecute(strJson);
                List<DataSongs> data = new ArrayList<>();
                JSONObject dataJsonObj = null;

                try {
                    dataJsonObj = new JSONObject(strJson);
                    JSONArray songs = dataJsonObj.getJSONArray("Songs");

                    for (int i = 0; i < songs.length(); i++) {
                        JSONObject song = songs.getJSONObject(i);
                        /**
                         * you were wrong here
                         */
                        DataSongs songData = new DataSongs();

                        songData.songName = song.getString("song");
                        songData.songGenreID = song.getString("GenreID");
                        songData.songUserID = song.getString("UserID");
                        data.add(songData);
                        Log.e("songo", "SongName: " + data.get(i).songName);
                    }

                    mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
                    mAdapter = new RecyclerAdapter(MainActivity.this, data, mRecyclerView);
                    mRecyclerView.setHasFixedSize(true);
                    mLayoutManager = new LinearLayoutManager(MainActivity.this);
                    mRecyclerView.setAdapter(mAdapter);
                    mRecyclerView.setLayoutManager(mLayoutManager);

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

                pdLoading.dismiss();
            }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM