数据库更改时,RecyclerView不会更新

时间:2016-06-08 05:34:54

标签: java android android-fragments android-recyclerview sugarorm

我正在使用 Sugar ORM 在我的应用中实现数据持久性。我正在 RecyclerView 中显示我的数据库内容。问题是SugarORM没有加载器,因此在添加/删除数据库条目后,无法用新数据刷新RecyclerView 。我通过在 OnResume()中重新初始化我的适配器并在Recycler View中显示它来解决手机问题。但对于平板电脑来说,逻辑不起作用,因为片段永远不会进入OnPause

当我删除DetailsFragment中的条目时,我需要在我的FavouritesFragment中更新我的RecyclerView

这是Github链接https://github.com/Hackertronix/Project-Motion/tree/Stage_2

这是两个片段的代码

FavoritesFragment.java

package com.execube.genesis.views.fragments;

import android.app.ActivityOptions;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.execube.genesis.R;
import com.execube.genesis.model.Movie;
import com.execube.genesis.utils.API;
import com.orm.SugarRecord;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Prateek Phoenix on 6/7/2016.
 */
public class FavouritesFragment extends Fragment {

    public static final String TAG= "FAVOURITES";
    private static final String FAVOURITE_MOVIES_ARRAY = "favourite_movies";
    private List<Movie> mMovies=new ArrayList<>();
    private RecyclerView mFavouritesRecyclerView;
    ArrayList<Movie> moviesArrayList;
    private FavouritesAdapter mAdapter;
    private TabLayout mTabLayout;

    public FavouritesFragment() {
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.v(TAG,"In OnCreate()");
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onPause() {
        Log.v(TAG,"OnPause() Called");
        super.onPause();
    }

    @Override
    public void onResume() {
     /*   Sugar ORM does not have a Loader
          so to refresh the recyclerview adapter I am reinitializing it*/

        Log.v(TAG,"OnResume() Called");
        mMovies=Movie.listAll(Movie.class);
        mAdapter=new FavouritesAdapter();
        mFavouritesRecyclerView.setAdapter(mAdapter);
        mFavouritesRecyclerView.invalidate();
        super.onResume();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.v(TAG,"In OnCreateView()");
        View view = inflater.inflate(R.layout.fragment_favourites,container,false);
        mFavouritesRecyclerView=(RecyclerView)view.findViewById(R.id.favourites_recyclerview);

        if(savedInstanceState!=null&&savedInstanceState.containsKey(FAVOURITE_MOVIES_ARRAY))
        {
            Log.v(TAG,"Restoring State");
            mMovies=savedInstanceState.getParcelableArrayList(FAVOURITE_MOVIES_ARRAY);
        }

        else {
            mMovies=  Movie.listAll(Movie.class);
        }



        if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){

            mFavouritesRecyclerView.setLayoutManager(new
                    GridLayoutManager(getActivity(), 2));
        }
        else{
            mFavouritesRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
        }
        mAdapter= new FavouritesAdapter();
        mFavouritesRecyclerView.setAdapter(mAdapter);
        mFavouritesRecyclerView.invalidate();
        return view;
    }



    private class FavouritesHolder extends RecyclerView.ViewHolder implements View.OnClickListener
    {
        private ImageView mPosterImageView;
        private Movie mMovie;
        public FavouritesHolder(View itemView) {
            super(itemView);
            mPosterImageView=(ImageView)itemView.findViewById(R.id.poster);
            itemView.setOnClickListener(this);
        }

        public void bind(Movie movie)
        {
            mMovie=movie;
            Picasso mPicasso= Picasso.with(getActivity());
            mPicasso.setIndicatorsEnabled(true);

            mPicasso.load(API.IMAGE_URL+API.IMAGE_SIZE_500+mMovie.getPosterPath())
                    .placeholder(R.drawable.placeholder)
                    .error(R.drawable.error)
                    .into(mPosterImageView);
        }

        @Override
        public void onClick(View v) {

            ActivityOptions options=ActivityOptions.makeSceneTransitionAnimation(getActivity(),mPosterImageView,"posterImage");
            ((openDetailsListener)getActivity()).openDetails(mMovie,options);
        }
    }



    @Override
    public void onSaveInstanceState(Bundle outState) {
        moviesArrayList=new ArrayList<>(mMovies);
        Log.v(TAG,"Saving State");
        outState.putParcelableArrayList(FAVOURITE_MOVIES_ARRAY,moviesArrayList);
        super.onSaveInstanceState(outState);
    }

    private class FavouritesAdapter extends RecyclerView.Adapter<FavouritesHolder>
    {


        @Override
        public FavouritesHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view= LayoutInflater.from(getActivity()).inflate(R.layout.movie_item,parent,false);
            return new FavouritesHolder(view);
        }

        @Override
        public void onBindViewHolder(FavouritesHolder holder, int position) {

            Movie movie= mMovies.get(position);
            holder.bind(movie);
        }

        @Override
        public int getItemCount() {
            return mMovies.size();
        }
    }
    public interface openDetailsListener{
        void openDetails(Movie movie,ActivityOptions options);
    }
}

DetailsFragment.java

package com.execube.genesis.views.fragments;

import android.annotation.TargetApi;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;

import com.execube.genesis.R;
import com.execube.genesis.model.Movie;
import com.execube.genesis.model.Review;
import com.execube.genesis.model.Trailer;
import com.execube.genesis.utils.API;
import com.execube.genesis.utils.JSONParser;
import com.execube.genesis.utils.OkHttpHandler;
import com.orm.SugarRecord;
import com.squareup.picasso.Picasso;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import okhttp3.Call;
import okhttp3.Response;

import static com.execube.genesis.R.drawable.ic_favorite_black_24dp;


/**
 * Created by Prateek Phoenix on 4/30/2016.
 */
public class DetailsFragment extends Fragment {
    private static final String TAG = "DETAILS";
    private static final int DEFAULT_NUM_COLORS = 5;

    private Movie mMovie;
    private Movie entry,tempMovie;
    private List<Movie> movie;
    public Intent intent;

    private TextView mDetailTitle;
    private TextView mReleaseDate;
    private TextView mOverview;
    private TextView mOverviewHeader;
    private TextView mReviesHeader;
    private TextView mTrailersHeader;

    private ImageView mBackdrop;
    private Toolbar mToolbar;

    private RatingBar mRatingBar;

    private ArrayList<Review> mReviews=new ArrayList<>();
    private ArrayList<Trailer> mTrailers=new ArrayList<>();

    public static final String MOVIE_REVIEWS_ARRAY ="movie_details";
    private static final String MOVIE_TRAILERS_ARRAY = "movie_reviews";
    private Typeface fontBold;
    private Typeface fontMediumLight;
    private Typeface fontMedium;

    private RecyclerView mReviewRecyclerView;
    private RecyclerView mTrailerRecyclerView;

    private ProgressBar mReviewsProgressbar;
    private ProgressBar mTrailersProgressbar;
    private CoordinatorLayout mCoordinatorLayout;
    private CardView mReviewsCardView;
    private FloatingActionButton mFloatingActionButton;

    private ReviewsAdapter mReviewAdapter;
    private int NumOfReviews;
    private TrailersAdapter mTrailerAdapter;

    private String id;
    private boolean isFav;
    public DetailsFragment() {

    }

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

    @Override
    public void onSaveInstanceState(Bundle outState) {
        Log.v(TAG,"Saving state in onSaveInstanceState");
        outState.putParcelableArrayList(MOVIE_REVIEWS_ARRAY,mReviews);
        outState.putParcelableArrayList(MOVIE_TRAILERS_ARRAY,mTrailers);
        super.onSaveInstanceState(outState);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_detail, container, false);


        mBackdrop = (ImageView) view.findViewById(R.id.details_poster);

        mDetailTitle = (TextView) view.findViewById(R.id.detail_title_text);
        mReleaseDate = (TextView) view.findViewById(R.id.release_date);
        mOverview = (TextView) view.findViewById(R.id.overview);
        mOverviewHeader = (TextView) view.findViewById(R.id.overview_header);
        mReviesHeader=(TextView)view.findViewById(R.id.review_header);
        mTrailersHeader=(TextView)view.findViewById(R.id.trailer_header);

        mRatingBar = (RatingBar) view.findViewById(R.id.movie_rating);
        mCoordinatorLayout=(CoordinatorLayout)view.findViewById(R.id.coordinator_layout);
        mReviewRecyclerView= (RecyclerView)view.findViewById(R.id.review_recycler_view);
        mTrailerRecyclerView=(RecyclerView)view.findViewById(R.id.trailer_recycler_view);

        mReviewsProgressbar=(ProgressBar)view.findViewById(R.id.reviews_progressbar);
        mTrailersProgressbar=(ProgressBar)view.findViewById(R.id.trailers_progressbar);
        mFloatingActionButton=(FloatingActionButton)view.findViewById(R.id.fab);

        mReviewsCardView= (CardView) view.findViewById(R.id.reviews_card);


        intent = getActivity().getIntent();
        Bundle bundle=getArguments();
        mMovie=bundle.getParcelable("PARCEL");
        tempMovie=mMovie;
        id = String.valueOf(mMovie.getMovieId());


        checkFav();
        mFloatingActionButton.show();

        assert mMovie != null;

        //PREPPING THE URL FOR QUERY

        String reviewQueryUrl = API.MOVIES_BASE_URL + id + "/reviews" + API.API_KEY;
        String trailerQueryUrl = API.MOVIES_BASE_URL + id + "/videos" + API.API_KEY;



        mDetailTitle.setText(mMovie.getTitle());
        mReleaseDate.setText(mMovie.getReleaseDate());
        mRatingBar.setProgress((int) mMovie.getVoteAverage());
        mOverview.setText(mMovie.getOverview());


        if (Build.VERSION.SDK_INT != 21) {
            fontBold = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Gotham-Rounded-Bold.ttf");
            fontMedium = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Gotham-Rounded-Medium.ttf");
            fontMediumLight = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Gotham-Rounded-Book_.ttf");


            mDetailTitle.setTypeface(fontBold);
            mReleaseDate.setTypeface(fontMedium);
            mOverview.setTypeface(fontMediumLight);
            mOverviewHeader.setTypeface(fontBold);
            mReviesHeader.setTypeface(fontBold);
            mTrailersHeader.setTypeface(fontBold);
        }



        //FETCHING JSON HERE
        if(savedInstanceState!=null&&savedInstanceState.containsKey(MOVIE_REVIEWS_ARRAY))
        {
            Log.v(TAG,"Restoring from bundle");
            mReviews=savedInstanceState.getParcelableArrayList(MOVIE_REVIEWS_ARRAY);
            mTrailers=savedInstanceState.getParcelableArrayList(MOVIE_TRAILERS_ARRAY);

            mReviewsProgressbar.setVisibility(View.GONE);
            mTrailersProgressbar.setVisibility(View.GONE);

        }

        else {
            OkHttpHandler reviewsHandler = new OkHttpHandler(reviewQueryUrl, reviewsCallback);
            reviewsHandler.fetchData();

            OkHttpHandler trailersHandler= new OkHttpHandler(trailerQueryUrl, trailersCallback);
            trailersHandler.fetchData();

        }

        Picasso.with(getActivity()).load(API.IMAGE_URL + API.IMAGE_SIZE_500 + mMovie.getPosterPath())
                .placeholder(R.drawable.placeholder)
                .error(R.drawable.error)
                .into(mBackdrop);
        getActivity().startPostponedEnterTransition();





        mReviewRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mReviewAdapter= new ReviewsAdapter();
        mReviewRecyclerView.setAdapter(mReviewAdapter);

        LinearLayoutManager layoutmanager= new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL,false);
        mTrailerRecyclerView.setLayoutManager(layoutmanager);
        mTrailerAdapter= new TrailersAdapter();
        mTrailerRecyclerView.setAdapter(mTrailerAdapter);

        return view;
    }

    private void checkFav() {
        movie=new ArrayList<>();
        movie=SugarRecord.find(Movie.class,"m_id=?",id);
        if(movie.size()==0)
        {
            Log.v(TAG,"Null");

            mFloatingActionButton.setImageResource(R.drawable.ic_favorite_border_black_24dp);
        }
        else {
            Log.v(TAG,"NOT Null");

            mFloatingActionButton.setImageResource(R.drawable.ic_favorite_black_24dp);
        }

        mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
             movie=SugarRecord.find(Movie.class,"m_id=?",id);
                if(movie.size()>0)
                {
                    entry = movie.get(0);
                    entry.delete();
                    mFloatingActionButton.setImageResource(R.drawable.ic_favorite_border_black_24dp);
                    Snackbar snackbar = Snackbar.make(mCoordinatorLayout,"Movie removed from Favourites!!",Snackbar.LENGTH_SHORT);
                    View view= snackbar.getView();
                    TextView textView = (TextView)view.findViewById(android.support.design.R.id.snackbar_text);
                    textView.setTextColor(Color.YELLOW);
                    snackbar.show();
                }
                else
                {
                    entry = tempMovie;
                    entry.save();
                    mFloatingActionButton.setImageResource(R.drawable.ic_favorite_black_24dp);
                    Snackbar snackbar = Snackbar.make(mCoordinatorLayout,"Movie added to Favourites!!",Snackbar.LENGTH_SHORT);
                    View view= snackbar.getView();
                    TextView textView = (TextView)view.findViewById(android.support.design.R.id.snackbar_text);
                    textView.setTextColor(Color.YELLOW);
                    snackbar.show();
                }

            }
        });
    }


    //OKHTTP CALLBACK FOR NETWORK CALL
    private okhttp3.Callback reviewsCallback = new okhttp3.Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            //TODO handle failure on UI thread
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {

            try {
                String JSONData= response.body().string();
                JSONObject jsonObject = new JSONObject(JSONData);
                NumOfReviews = jsonObject.getInt("total_results");
                JSONParser parser = new JSONParser();
                Log.v(TAG,JSONData);
                mReviews=parser.parseReviews(JSONData);



            } catch (JSONException e) {}

            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    if(mReviewAdapter!=null)
                    {
                        mReviewsProgressbar.setVisibility(View.GONE);
                        mReviewAdapter.notifyDataSetChanged();
                    }
                }
            });

            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (NumOfReviews==0)
                    {
                        mReviewsCardView.setVisibility(View.INVISIBLE);
                    }
                }
            });
        }
    };

    private okhttp3.Callback trailersCallback = new okhttp3.Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            //TODO handle failure on UI thread
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {

            try {
                String json1= response.body().string();
                JSONParser parser= new JSONParser();
                Log.v(TAG, json1);
                mTrailers = parser.parseTrailers(json1);

            } catch (JSONException e) {}

            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(mTrailerAdapter!=null)
                    {
                        mTrailersProgressbar.setVisibility(View.GONE);
                        mTrailerAdapter.notifyDataSetChanged();
                    }
                }
            });
        }
    };

    private class ReviewViewHolder extends RecyclerView.ViewHolder{
        private TextView mAuthorText;
        private TextView mReviewText;
        private Review mReview;

        public ReviewViewHolder(View itemView) {
            super(itemView);
            mAuthorText= (TextView) itemView.findViewById(R.id.author_textview);
            mReviewText= (TextView) itemView.findViewById(R.id.review_textview);

        }

        public void bind(Review review)
        {
            mReview= review;

            mAuthorText.setText(mReview.getAuthor());
            mReviewText.setText(mReview.getContent());

            if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
            {
                mAuthorText.setTypeface(fontBold);
                mReviewText.setTypeface(fontMediumLight);
            }


        }
    }

    private class ReviewsAdapter extends RecyclerView.Adapter<ReviewViewHolder>{

        @Override
        public ReviewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view= LayoutInflater.from(getActivity()).inflate(R.layout.review_item,parent,false);
            return new ReviewViewHolder(view);
        }

        @Override
        public void onBindViewHolder(ReviewViewHolder holder, int position) {
            Review review= mReviews.get(position);
            holder.bind(review);
        }

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

    private class TrailerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private ImageView mTrailerThumbnail;
        private Trailer mTrailer;

        public TrailerViewHolder(View itemView) {
            super(itemView);

            mTrailerThumbnail=(ImageView)itemView.findViewById(R.id.trailer_thumbnail);
            itemView.setOnClickListener(this);
        }

        public void bind(Trailer trailer)
        {
            mTrailer=trailer;

            Picasso picasso =Picasso.with(getActivity());
            picasso.setIndicatorsEnabled(true);
            picasso.load(API.YOUTUBE_THUMBNAIL_URL+mTrailer.getKey()+API.THUMBNAIL_QUALITY)
                    .into(mTrailerThumbnail);

        }

        @Override
        public void onClick(View v) {

            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(API.YOUTUBE_TRAILER_URL+mTrailer.getKey()));
            startActivity(intent);

        }
    }

    private class TrailersAdapter extends RecyclerView.Adapter<TrailerViewHolder>
    {

        @Override
        public TrailerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view= LayoutInflater.from(getActivity()).inflate(R.layout.trailer_item,parent,false);
            return new TrailerViewHolder(view);
        }

        @Override
        public void onBindViewHolder(TrailerViewHolder holder, int position) {
            Trailer trailer= mTrailers.get(position);
            holder.bind(trailer);
        }

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

}

2 个答案:

答案 0 :(得分:1)

您可以使用界面在片段(Here's a question I asked an year ago and the accepted answer was really easy to understand)之间进行通信。

然后,您需要在callBack方法中调用mAdapter.notifyDataSetChanged()

答案 1 :(得分:1)

我提出了一种方法来解决这个问题。

class TabletActivity extends Activity implements DetailFragment.Callback {
    public void onCreate(Bundle savedInstanceState){
         //Initialise fragments  

    }
    void onItemDelete(){
         // find the Master Fragment using FragmentManager;
         MasterFragment f = (MasterFragment) getFragmentManager().findFragmentById(); 
         if (f != null){
             f.somethingHasChanged();
         }
    }
}

class DetailFragment extends Fragment {
    private Callback callback;
    public onAttach(Context context){
         this.callback =  (Context) context;
    }
    public void onViewCreated(View v, Bundle b){
         Button b;
         b.setOnClickListener(new View.OnClickListener(){
              public void onClick(View v){
                  callback.onItemDelete(); 
              }
         )
    }

    public interface Callback {
        void onItemDelete();
    }


}
class MasterFragment extends Fragment {
    public void somethingHasChanged(){
          adapter.notifyDatasetChanged();
    }
}

DetailFragment是我们发起更改的地方,MasterFragment正在使用这些更改。这种沟通不是通过活动。我个人不建议您按照建议使用OnResume()中的notifyAdapterChanges,因为无法保证在您的数据发生更改后,onResume将立即调用。

了解详情: https://developer.android.com/training/basics/fragments/communicating.html