首页 > 解决方案 > 无法在房间数据库 Android 中插入值

问题描述

我正在尝试插入有关电影的信息,但出现此错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'void kawi15.myapplication.database.DatabaseViewModel.addWatchlistMovie(info.movito.themoviedbapi.model.MovieDb)' on a null object reference

我确定 Movie 不为空,因为我有 Toast 向我显示有关这部电影的信息。

我发现我需要DatabaseViewModel在我的 OnCreate() 中进行初始化:

databaseViewModel = new ViewModelProvider(this).get(DatabaseViewModel.class);

但我在 OnCreate 和 OnCreateView 以及它的错误中都尝试了这个:

new ViewModelProvider(this)

我尝试将 getContext() 或其他一些东西放在那里,但这里没有任何效果。

这是我的实体类:

@Entity
public class Watchlist {
    @PrimaryKey
    @ColumnInfo(name = "id")
    private int movieId;

    @ColumnInfo(name = "movie_title")
    private String movieTitle;

    @ColumnInfo(name = "poster_path")
    private String posterPath;

    @ColumnInfo(name = "overview")
    private String overview;

    @ColumnInfo(name = "release_date")
    private String releaseDate;

and getters and setters for all

我的道课:

@Dao
public interface WatchlistDao {
    @Query("SELECT * FROM watchlist ORDER BY movie_title ASC")
    List<Watchlist> getAll();

    @Insert
    void addMovie(Watchlist watchlistMovie);
}

视图模型类:

public class DatabaseViewModel extends AndroidViewModel {
    private AppDatabase db;

    public DatabaseViewModel(@NonNull Application application) {
        super(application);
        db = AppDatabase.getDatabase(application);
    }

    public void addWatchlistMovie(MovieDb movieDb){
        Watchlist addedMovie = new Watchlist();
        addedMovie.setMovieId(movieDb.getId());
        addedMovie.setMovieTitle(movieDb.getOriginalTitle());
        addedMovie.setOverview(movieDb.getOverview());
        addedMovie.setPosterPath(movieDb.getPosterPath());
        addedMovie.setReleaseDate(movieDb.getReleaseDate());

        db.watchlistDao().addMovie(addedMovie);
    }

我从要插入数据库的列表中单击电影的片段类:

public class FragmentOne extends Fragment /*implements CustomAdapter.ListItemClickListener*/{

    private static RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;
    private DatabaseViewModel databaseViewModel;
    private static RecyclerView recyclerView;
    private List<MovieDb> data;
    //private CustomAdapter.ListItemClickListener mOnClickListener;

    public static FragmentOne newInstance() {
        FragmentOne fragment = new FragmentOne();
        return fragment;
    }

    /*@Override
    public void onListItemClick(int position) {
        Toast.makeText(getContext(), data.get(position).getOriginalTitle(), LENGTH_SHORT).show();
    }*/

    public class MovieTask extends AsyncTask<Void, Void, List<MovieDb>> {
        @Override
        protected List<MovieDb> doInBackground(Void... voids) {
            MovieResultsPage movies = new TmdbApi("f753872c7aa5c000e0f46a4ea6fc49b2").getMovies().getUpcoming("en-US", 1, "US");
            List<MovieDb> listMovies = movies.getResults();

            return listMovies;
        }

        @Override
        protected void onPostExecute(List<MovieDb> movieDb) {
            data = movieDb;
            adapter = new CustomAdapter(data);
            ((CustomAdapter) adapter).setOnMovieDbClicked(movieDb2 -> {
                Toast.makeText(getActivity(), movieDb2.getReleaseDate(), LENGTH_SHORT).show();
                databaseViewModel.addWatchlistMovie(movieDb2);
            });
            recyclerView.setAdapter(adapter);
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View returnView = inflater.inflate(R.layout.fragment_one, container, false);


        recyclerView = (RecyclerView) returnView.findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);

        layoutManager = new LinearLayoutManager(getContext());  // ???
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());


        MovieTask mt = new MovieTask();
        mt.execute();

        return returnView;
    }


}

和我的适配器类,也许不是必需的:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder>{

    private List<MovieDb> dataSet;
    private OnMovieDbClicked onMovieDbClicked;


    public void setOnMovieDbClicked(OnMovieDbClicked onMovieDbClicked) {
        this.onMovieDbClicked = onMovieDbClicked;
    }
    //final private ListItemClickListener mOnClickListener;

    public class MyViewHolder extends RecyclerView.ViewHolder /*implements View.OnClickListener*/{

        TextView textViewName;
        TextView textViewVersion;
        ImageView imageViewIcon;
        //private ListItemClickListener mOnClickListener;

        public MyViewHolder(View itemView) {
            super(itemView);
            this.textViewName = (TextView) itemView.findViewById(R.id.text1);
            this.textViewVersion = (TextView) itemView.findViewById(R.id.text2);
            this.imageViewIcon = (ImageView) itemView.findViewById(R.id.imageView);

            itemView.setOnClickListener(view -> {
                int pos = getAdapterPosition();

                if (onMovieDbClicked != null && pos != RecyclerView.NO_POSITION) {
                    MovieDb movieDb = dataSet.get(pos);
                    onMovieDbClicked.movieDbClicked(movieDb);
                }
            });
            //itemView.setOnClickListener(this);
            //itemView.setOnClickListener(CustomAdapter.myOnClickListener);
        }

        /*@Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            mOnClickListener.onListItemClick(position);
        }*/
    }

    public CustomAdapter(List<MovieDb> data /*ListItemClickListener mOnClickListener*/) {
        this.dataSet = data;
        //this.mOnClickListener = mOnClickListener;
    }

    public interface OnMovieDbClicked {
        void movieDbClicked(MovieDb movieDb);
    }

    /*public interface ListItemClickListener{
        void onListItemClick(int position);
    }*/

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent,
                                           int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.cards_layout, parent, false);

        //view.setOnClickListener(FragmentOne.myOnClickListener);

        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {

        TextView textViewName = holder.textViewName;
        TextView textViewVersion = holder.textViewVersion;
        ImageView imageView = holder.imageViewIcon;
        Glide.with(imageView).load("https://image.tmdb.org/t/p/w500" + dataSet.get(listPosition).getPosterPath()).into(imageView);

        textViewName.setText(dataSet.get(listPosition).getOriginalTitle());
        textViewVersion.setText(dataSet.get(listPosition).getReleaseDate());


    }


    @Override
    public int getItemCount() {
        if(dataSet == null){
            return 0;
        }
        return dataSet.size();
    }
}

标签: javaandroidandroid-room

解决方案


您还没有初始化您的databaseViewModel任何地方,因此预计会出现 NPE。确保在访问之前填写该字段MovieTask


推荐阅读