1

설탕 ORM을 사용하여 앱에 데이터 지속성을 구현했습니다. 내 데이터베이스 내용을 RecyclerView에 표시하고 있습니다. 문제는 SugarORM에 로더가 없으므로 데이터베이스에 항목을 추가/삭제 한 후 RecyclerView을 최신 데이터로 새로 고칠 방법이 없습니다. 내 어댑터를 OnResume()에 다시 초기화하고 Recycler보기에 표시하여 전화 문제를 해결했습니다. 그러나 조각의 경우 절대로 OnPause으로 이동하지 않으므로 논리가 작동하지 않습니다. 내 DetailsFragment데이터베이스가 변경 될 때 RecyclerView가 업데이트되지 않습니다.

에서 항목을 제거 할 때

나는 여기에 Github에서 링크 https://github.com/Hackertronix/Project-Motion/tree/Stage_2

여기 두 조각

FavoritesFragment

에 대한 코드의의 내 FavouritesFragment 내 RecyclerView을 업데이트해야합니다. 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(); 
     } 
    } 

} 

답변

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

+0

덕분에이 쉽게 구현할 보인다. 일단 내가 그것을 만들면 나는 돌아올거야. –

관련 문제