Android Recycler查看和共享首选项

时间:2015-10-03 20:28:51

标签: android

我正在创建一个使用recyclelerView的简单应用程序,该应用程序由来自在线服务器的数据填充。数据显示在自定义的cardview布局中,该布局具有收藏夹按钮。我在recyclerView中实现收藏夹按钮时遇到了麻烦,而且应用程序一直在崩溃。

logcat的

10-03 23:22:06.609  23785-23785/com.smartdevelopers.kandie.nicedrawer E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.smartdevelopers.kandie.nicedrawer, PID: 23785
    java.lang.NullPointerException
            at com.smartdevelopers.kandie.nicedrawer.newsAdapter.OtherNewsAdapter.checkFavoriteItem(OtherNewsAdapter.java:102)
            at com.smartdevelopers.kandie.nicedrawer.newsAdapter.OtherNewsAdapter.onBindViewHolder(OtherNewsAdapter.java:64)
            at com.smartdevelopers.kandie.nicedrawer.newsAdapter.OtherNewsAdapter.onBindViewHolder(OtherNewsAdapter.java:25)
            at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5084)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4385)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4278)
            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1947)
            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1359)
            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1322)
            at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:556)
            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2673)
            at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2971)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:581)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1742)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1651)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:450)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1742)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1651)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1043)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:450)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1742)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1651)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:450)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1742)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1651)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:450)
            at android.view.View.layout(View.java:15125)
            at android.view.ViewGroup.layout(ViewGroup.java:4862)
            at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2317)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2023)
            at android.view.ViewRootImpl.doT

OtherNewsAdapter.java

public class OtherNewsAdapter extends RecyclerView.Adapter<OtherNewsAdapter.ViewHolder> {
    private List<Latest> feedItemList;
    private Context mContext;

    SharedPreference sharedPreference;    

    public OtherNewsAdapter(Context context, List<Latest> feedItemList) {
        this.feedItemList = feedItemList;
        this.mContext = context;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_other_news, null);
        ViewHolder mh = new ViewHolder(v);

        return mh;
    }
    //method to delete
    public void delete(int position){
        feedItemList.remove(position);
        notifyItemRemoved(position);    
    }

    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
        final Latest feedItem = feedItemList.get(i);

        Picasso.with(mContext).load(feedItem.getArticleImage())
                .error(R.drawable.placeholder)
                .placeholder(R.drawable.placeholder)
                .into(viewHolder.thumbnail);

        viewHolder.title.setText(Html.fromHtml(feedItem.getExcerpt()));

        /*If a product exists in shared preferences then set heart_red drawable
         * and set a tag*/
        if (checkFavoriteItem(feedItem)) {
            viewHolder.favImage.setImageResource(R.drawable.heart_red);
            viewHolder.favImage.setTag("red");
            addItem(feedItem);
        } else {
            viewHolder.favImage.setImageResource(R.drawable.heart_grey);
            viewHolder.favImage.setTag("grey");
            addItem(feedItem);
        }   
    }

    @Override
    public int getItemCount() {
        return (null != feedItemList ? feedItemList.size() : 0);
    }

    View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            OtherNewsRowHolder holder = (OtherNewsRowHolder) view.getTag();
            int position = holder.getPosition();

            Latest feedItem = feedItemList.get(position);
            Toast.makeText(mContext, feedItem.getExcerpt(), Toast.LENGTH_SHORT).show();
        }
    };    

    public void addItem(Latest lat){
        feedItemList.add(lat);
        notifyDataSetChanged();
    }
    /*Checks whether a particular product exists in SharedPreferences*/
    public boolean checkFavoriteItem(Latest checkProduct) {
        boolean check = false;
        List<Latest> favorites = sharedPreference.getFavorites(mContext);
        if (favorites != null) {
            for (Latest product : favorites) {
                if (product.equals(checkProduct)) {
                    check = true;
                    break;
                }
            }
        }
        return check;
    }    


    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        protected ImageView thumbnail, favImage;
        protected TextView title;

        public ViewHolder(View itemView) {
            super(itemView);
            this.thumbnail = (ImageView) itemView.findViewById(R.id.otherImage);
            this.title = (TextView) itemView.findViewById(R.id.otherExcerpt);
            this.favImage = (ImageView) itemView.findViewById(R.id.imgbtn_favorite);
           favImage.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {

            String tag = favImage.getTag().toString();
            if (tag.equalsIgnoreCase("grey")) {
                sharedPreference.addFavorite(mContext, feedItemList.get(getItemCount()));
                Toast.makeText(mContext,
                        mContext.getResources().getString(R.string.add_favr),
                        Toast.LENGTH_SHORT).show();

                favImage.setTag("red");
                favImage.setImageResource(R.drawable.heart_red);
            } else {
                sharedPreference.removeFavorite(mContext, feedItemList.get(getItemCount()));
                favImage.setTag("grey");
                favImage.setImageResource(R.drawable.heart_grey);
                Toast.makeText(mContext,
                        mContext.getResources().getString(R.string.remove_favr),
                        Toast.LENGTH_SHORT).show();
            }    
        }   
    }
}

SharedPreference.java

 public class SharedPreference {
    public static final String PREFS_NAME = "NEWS_APP";
    public static final String FAVORITES = "Article_Favorite";

    public SharedPreference() {
        super();
    }
    // This four methods are used for maintaining favorites.
    public void saveFavorites(Context context, List<Latest> favorites) {
        SharedPreferences settings;
        SharedPreferences.Editor editor;

        settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        editor = settings.edit();

        Gson gson = new Gson();
        String jsonFavorites = gson.toJson(favorites);

        editor.putString(FAVORITES, jsonFavorites);

        editor.commit();
    }
    public void addFavorite(Context context, Latest product) {
        List<Latest> favorites = getFavorites(context);
        if (favorites == null)
            favorites = new ArrayList<Latest>();
        favorites.add(product);
        saveFavorites(context, favorites);
    }

    public void removeFavorite(Context context, Latest product) {
        ArrayList<Latest> favorites = getFavorites(context);
        if (favorites != null) {
            favorites.remove(product);
            saveFavorites(context, favorites);
        }
    }

    public ArrayList<Latest> getFavorites(Context context) {
        SharedPreferences settings;
        List<Latest> favorites;

        settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

        if (settings.contains(FAVORITES)) {
            String jsonFavorites = settings.getString(FAVORITES, null);
            Gson gson = new Gson();
            Latest[] favoriteItems = gson.fromJson(jsonFavorites, Latest[].class);

            favorites = Arrays.asList(favoriteItems);
            favorites = new ArrayList<Latest>(favorites);
        } else
            return null;

        return (ArrayList<Latest>) favorites;
    }
}

SportsFragment.java

public class SportsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
    private List<Latest> feedsList;
    private RecyclerView mRecyclerView;
    private OtherNewsAdapter adapter;
    private ProgressBar progressBar;
    private SwipeRefreshLayout swipeSports;
    final String url = "http://javatechig.com/?json=get_recent_posts&count=45";
    public static final String TAG = "sports";
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.sports_fragment_layout, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getActivity().setTitle(R.string.sports);

        swipeSports=(SwipeRefreshLayout) getActivity().findViewById(R.id.swipeSports);
        swipeSports.setOnRefreshListener(this);
        // Initialize recycler view
        mRecyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_sports);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        progressBar = (ProgressBar) getActivity().findViewById(R.id.materialProgress);
        progressBar.setVisibility(View.VISIBLE);

        //Async Task
        // Downloading data from below url

        new AsyncHttpTask().execute(url);
    }

    public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) {
        swipeSports.setColorScheme(colorRes1, colorRes2, colorRes3, colorRes4);
    }

    @Override
    public void onRefresh() {
        new AsyncHttpTask().execute(url);
        setColorScheme(R.color.color_scheme_1_1, R.color.color_scheme_1_2,
                R.color.color_scheme_1_3, R.color.color_scheme_1_4);
    }
    public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

        @Override
        protected void onPreExecute() {
        //getActivity().setProgressBarIndeterminateVisibility(true);
        }

        @Override
        protected Integer doInBackground(String... params) {
            Integer result = 0;
            HttpURLConnection urlConnection;
            try {
                URL url = new URL(params[0]);
                urlConnection = (HttpURLConnection) url.openConnection();
                int statusCode = urlConnection.getResponseCode();

                // 200 represents HTTP OK
                if (statusCode == 200) {
                    BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = r.readLine()) != null) {
                        response.append(line);
                    }
                    parseResult(response.toString());
                    result = 1; // Successful
                } else {
                    result = 0; //"Failed to fetch data!";
                }
            } catch (Exception e) {
                Log.d(TAG, e.getLocalizedMessage());
            }
            return result; //"Failed to fetch data!";
        }

        @Override
        protected void onPostExecute(Integer result) {
            // Download complete. Let us update UI
            progressBar.setVisibility(View.GONE);



            if (result == 1) {
                if(swipeSports.isRefreshing()){
                    swipeSports.setRefreshing(false);
                }


                adapter = new OtherNewsAdapter(getActivity(), feedsList);
                mRecyclerView.setAdapter(adapter);
            } else {
                adapter=null;
                mRecyclerView.setAdapter(adapter);
                if(swipeSports.isRefreshing()){
                    swipeSports.setRefreshing(true);
                }
              //error.setVisibility(View.VISIBLE);
            }
        }
    }

    private void parseResult(String result) {
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("posts");
            feedsList = new ArrayList<>();

            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = posts.optJSONObject(i);
                Latest item = new Latest();
                item.setExcerpt(post.optString("title"));
                item.setArticleImage(post.optString("thumbnail"));

                feedsList.add(item);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

row_other_news.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="5dp"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="5dp"
        android:paddingTop="5dp"
        android:paddingLeft="5dp"
        >

        <ImageView
            android:id="@+id/otherImage"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:scaleType="centerCrop"
            android:tint="@color/photo_tint"
            android:contentDescription="@string/country"
            android:layout_alignParentLeft="true"
            />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/otherExcerpt"
            android:layout_toRightOf="@+id/otherImage"
            android:padding="16dp"/>

        <ImageView
            android:id="@+id/imgbtn_favorite"
            android:layout_width="20dp"
            android:layout_marginTop="5dp"
            android:layout_height="20dp"
            android:layout_below="@+id/otherExcerpt"
            android:layout_alignParentRight="true"
            android:layout_marginRight="3dp"
            android:background="@null"
            android:contentDescription="@string/favorites"
            android:clickable="true"/>    
    </RelativeLayout>

</android.support.v7.widget.CardView>

2 个答案:

答案 0 :(得分:0)

您忘记了创建共享偏好设置对象SharedPreference sharedPreference

答案 1 :(得分:0)

嗨,大家好,我知道这是一个很老的帖子,但这可能会对我这样做有所帮助

您应该将字段boolean isFavourite添加到Latest。什么时候 用户添加到您设置为true的收藏夹。在onBindViewHolder中 你必须检查状态并设置ui。 - AdamMiśtal

当我遇到这个时,我花了一段时间才真正得到了他所说的话并做了大卫所做的并且也停了下来,但后来我又回去读了一遍,重复了亚当说它击中了我

所以在最新添加

Private int Id; 在构造函数中添加 this.id =我想;

然后添加

@override
public boolean equals(Object obj) { 
  Latest latest = (Latest) obj;
  If(id != latest.I'd)
     return false;

  return true;
}

在适配器中,你已经有了一个boolean checkFavoriteItem,它将按原样运行

现在最重要的是确保您从服务器为每个对象提供的数据都有一个ID作为其唯一标识符