我正在创建一个使用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>
答案 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作为其唯一标识符