显示来自SQLite表列的数据,其中一列包含一个数组

时间:2019-06-05 10:52:45

标签: json android-sqlite

我设法仅使用数组的第一项来检索SQLite表,并将其放在UI的TextView中。无法获取数组的所有项目。从其余各列中,成功返回一个值。

JSON被解析,并作为可打包的ArrayList传递到Fragment,在列表中呈现。单击列表项会转到另一个显示所有项目详细信息的片段。

我一直在尝试编写一个for循环,该循环将数组中的字符串返回到TextView中,但是条件i < genresList.size()始终为false。我尝试使用while循环,但它仅返回列表的第一项。 我在互联网上找到的各种方法都行不通。

谢谢。

分析并插入到SQLite

private void parseJsonAndInsertToSQLIte(SQLiteDatabase db) throws JSONException {
        // parsing the json
        String jsonString = getJsonFileData();
        JSONArray moviesArray = new JSONArray(jsonString);
        ContentValues insertValues;

        for (int i = 0; i < moviesArray.length(); i++) {

            JSONObject jsonObject = moviesArray.getJSONObject(i);

            String title = jsonObject.getString("title");
            String imageUrl = jsonObject.getString("image");
            String rating = jsonObject.getString("rating");
            String releaseYear = jsonObject.getString("releaseYear");

            JSONArray genresArray = jsonObject.getJSONArray("genre");
            List<String> genres = new ArrayList<>();
            for (int k = 0; k < genresArray.length(); k++) {
                genres.add(genresArray.getString(k));
            }

            insertValues = new ContentValues();

            insertValues.put(Movie.TITLE, title);
            insertValues.put(Movie.IMAGE_URL, imageUrl);
            insertValues.put(Movie.RATING, rating);
            insertValues.put(Movie.RELEASE_YEAR, releaseYear);
            for (int k = 0; k < genresArray.length(); k++) {
                insertValues.put(Movie.GENRE, genres.get(k));
            }
            Log.i(TAG, "insertValues: " + genresArray);

            long res = db.insert(TABLE_NAME, null, insertValues);

            Log.i(TAG, "parsed and inserted to sql - row: " + res);
        }
    }

该项目的详细信息片段

public class MovieDetailsFragment extends Fragment{

... variables declarations come here...

    @Nullable
    @Override
    public View onCreateView(@NotNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_details_movie, container, false);

        Context context = getActivity();

        Bundle idBundle = getArguments();
        if (idBundle != null) {
            movieId = getArguments().getInt("id");
        }

        getDatabase = new GetDatabase(context);
        getDatabase.open();
        Cursor cursor = getDatabase.getMovieDetails(movieId);

... more irelevant code comes here...

        titleView = rootView.findViewById(R.id.movieTtlId);
        ratingView = rootView.findViewById(R.id.ratingId);
        releaseYearView = rootView.findViewById(R.id.releaseYearId);
        genreView = rootView.findViewById(R.id.genreID);

        String titleFromSQLite = cursor.getString(cursor.getColumnIndex(Movie.TITLE));
        String ratingFromSQLite = cursor.getString(cursor.getColumnIndex(Movie.RATING));
        String releaseYearFromSQLite = cursor.getString(cursor.getColumnIndex(Movie.RELEASE_YEAR));

        String genreFromSQLite;
        if(cursor.moveToFirst()) {
            do {
                genreFromSQLite = cursor.getString(cursor.getColumnIndex(Movie.GENRE));
                genres.add(genreFromSQLite);
            } while (cursor.moveToNext());
        }
        else{
            genreFromSQLite = cursor.getString(cursor.getColumnIndex(Movie.RELEASE_YEAR));
        }
        getDatabase.close();

//more irelevant code comes here

        genreView.setText(genreFromSQLite);
        genreView.setFocusable(false);
        genreView.setClickable(false);

        return rootView;
    }
}

从SQLite返回表的方法:

    public ArrayList<Movie> getMovies() {
        String[] columns = {
                Movie.ID,
                Movie.TITLE,
                Movie.IMAGE_URL,
                Movie.RATING,
                Movie.RELEASE_YEAR,
                Movie.GENRE
        };

        // sorting orders
        String sortOrder =
                Movie.RELEASE_YEAR + " ASC";
        ArrayList<Movie> moviesList = new ArrayList<>();

        Cursor cursor = db.query(TABLE_NAME, //Table to query
                columns,
                null,
                null,
                null,
                null,
                sortOrder);

        if (cursor.moveToFirst()) {
            do {
                Movie movie = new Movie();
                movie.setMovieId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Movie.ID))));
                movie.setTitle(cursor.getString(cursor.getColumnIndex(Movie.TITLE)));
                movie.setImageUrl(cursor.getString(cursor.getColumnIndex(Movie.IMAGE_URL)));
                movie.setRating(cursor.getDouble(cursor.getColumnIndex(Movie.RATING)));
                movie.setReleaseYear(cursor.getInt(cursor.getColumnIndex(Movie.RELEASE_YEAR)));

                List<String> genreArray = new ArrayList<>();
                while(cursor.moveToNext()){
                    String genre = cursor.getString(cursor.getColumnIndex(Movie.GENRE));
                    genreArray.add(genre);
                }

                movie.setGenre(Collections.singletonList(String.valueOf(genreArray)));

                // Adding a movie to the list
                moviesList.add(movie);

            } while (cursor.moveToNext());
        }
        Log.d(TAG, "The movies list from sqlite: " + moviesList);
        cursor.close();
        db.close();

        return moviesList;
    }

1 个答案:

答案 0 :(得分:1)

我相信您的问题在于:-

        for (int k = 0; k < genresArray.length(); k++) {
            insertValues.put(Movie.GENRE, genres.get(k));
        }

这将导致仅插入循环中的最后一个值,因为键/列名称(put的第一个参数)不会更改(并且可能不会,因为只有一列)。

您可以使用:-

        StringBuilder sb = new StringBuilder();
        for (int k = 0; k < genresArray.length(); k++) {
            if (k > 0) {
                sb.append(",");
            }
            sb.append(genres.get(k));
        }
        insertValues.put(Movie.GENRE, sb.toString());
  • 请注意,上面的代码是原则代码。它尚未经过测试或运行,因此可能包含错误。

这会将所有数据作为CSV插入GENRE列中。

但是,就利用数据库而言,这不是一个很好的方法。如果流派是一个单独的表,并且可能使用了映射表,那就更好了(但这应该是另一个问题)。

这也会引起您的问题:-

if (cursor.moveToFirst()) {
            do {
                Movie movie = new Movie();
                movie.setMovieId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Movie.ID))));
                movie.setTitle(cursor.getString(cursor.getColumnIndex(Movie.TITLE)));
                movie.setImageUrl(cursor.getString(cursor.getColumnIndex(Movie.IMAGE_URL)));
                movie.setRating(cursor.getDouble(cursor.getColumnIndex(Movie.RATING)));
                movie.setReleaseYear(cursor.getInt(cursor.getColumnIndex(Movie.RELEASE_YEAR)));

                List<String> genreArray = new ArrayList<>();
                while(cursor.moveToNext()){
                    String genre = cursor.getString(cursor.getColumnIndex(Movie.GENRE));
                    genreArray.add(genre);
                }

                movie.setGenre(Collections.singletonList(String.valueOf(genreArray)));

                // Adding a movie to the list
                moviesList.add(movie);

        } while (cursor.moveToNext());

也就是说,您移至游标的第一行,提取一些数据MoveieId,Title ... ReleaseYear。

然后

a)如果还有其他行,则移至下一行(这将是另一部Movie的下一行),直到到达最后一行为止,最后移至最后一行,将元素添加到genreArray。

b)如果Cursor genreArray中只有一行为空。

然后将1号和唯一的电影添加到movieList并返回。

每个电影中光标存在1个移动(行),每个电影中只有1个GENRE列。您必须提取该列中的数据,然后将数据拆分而不移动到genreArray中(请参见将创建CSV的上一个修复程序(请注意,如果数据包含逗号,则将其弄乱)) 。

IF ,您使用了先前的修复程序并将多种类型存储为CSV,那么您可以使用:-

if (cursor.moveToFirst()) {
            do {
                Movie movie = new Movie();
                movie.setMovieId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Movie.ID))));
                movie.setTitle(cursor.getString(cursor.getColumnIndex(Movie.TITLE)));
                movie.setImageUrl(cursor.getString(cursor.getColumnIndex(Movie.IMAGE_URL)));
                movie.setRating(cursor.getDouble(cursor.getColumnIndex(Movie.RATING)));
                movie.setReleaseYear(cursor.getInt(cursor.getColumnIndex(Movie.RELEASE_YEAR)));
                List<String> genreArray = new List<>(Arrays.asList((cursor.getString(cursor.getColumnIndex(Movie.GENRE))).split(",",0)));

                movie.setGenre(Collections.singletonList(String.valueOf(genreArray)));

                // Adding a movie to the list
                moviesList.add(movie);

        } while (cursor.moveToNext());
  • 请注意,上面的代码是原则代码。它尚未经过测试或运行,因此可能包含错误。