Please find me to solve this issue , i have a list of image url in a json api ,list url api is calling from background task and after compliting called notify method its not showing
but the Recyclerview doesn't refresh - only if I go back and reopen the activity - the new data is shown.
So how can I notify the adapter that there's new data to display?
1.WallpaperFragmentAdapter.java
public class WallpaperFragmentAdapter extends Fragment {
List<WallpaperMain> wallpaperList = new ArrayList<WallpaperMain>();
WallPaperAdapter wallPaperAdapter;
#Bind(R.id.recyclerView)
RecyclerView recyclerView;
private int tabId ;
public void settabId(int tabId){
this.tabId=tabId;
}
public static Fragment newInstance(Context context) {
WallpaperFragmentAdapter f = new WallpaperFragmentAdapter();
return f;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.content_main, null);
setUpView(root);
return root;
}
void setUpView(ViewGroup root){
ButterKnife.bind(this, root);
setUPList();
}
void setUPList(){
new WallPaperListDownlaoderTask().execute("http://localhost:8080/api/motivation/wallpaper/wallpaper");
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),3);
wallPaperAdapter = new WallPaperAdapter(wallpaperList,getActivity());
recyclerView.setAdapter(wallPaperAdapter);
recyclerView.setLayoutManager(gridLayoutManager);
System.out.println(wallPaperAdapter);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
Intent intent;
intent = new Intent(getActivity(), WallpaperDeatilsActivity.class);
startActivity(intent);
}
#Override
public void onLongClick(View view, int position) {
}
}));
}
class WallPaperListDownlaoderTask extends AsyncTask<String,Integer,JSONArray> {
OkHttpClient client = new OkHttpClient();
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected JSONArray doInBackground(String... params) {
String url =params[0];
Request request = new Request.Builder()
.url(url)
.build();
try{
Response response = client.newCall(request).execute();
String apiResponseString=response.body().string();
System.out.println("response.body().toString() ---- "+apiResponseString );
JSONArray jsonArray = new JSONArray(apiResponseString);
List<WallpaperMain> wallpaperMains = new ArrayList<>();
for(int index =0;index<jsonArray.length();index++){
try {
JSONObject wallpaperMainsJsonObj = jsonArray.getJSONObject(index);
WallpaperMain wallpaperMain = new WallpaperMain();
wallpaperMain.setId(wallpaperMainsJsonObj.getInt("id"));
Wallpaper wallpaper = new Wallpaper();
JSONObject wallpaperJsonObj = wallpaperMainsJsonObj.getJSONObject("wallpaper");
wallpaper.setLarge(wallpaperJsonObj.getString("large"));
wallpaperMain.setWallpaper(wallpaper);
wallpaperMains.add(wallpaperMain);
} catch (JSONException e) {
e.printStackTrace();
}
}
wallpaperList =wallpaperMains;
return null;
}catch (IOException e){
Log.v("",e.toString());
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(JSONArray jsonArray) {
super.onPostExecute(jsonArray);
System.out.println(wallPaperAdapter);
wallPaperAdapter.notifyDataSetChanged();
recyclerView.setAdapter(wallPaperAdapter);
System.out.println(wallpaperList.size());
}
}
}
2.WallPaperAdapter.java
public class WallPaperAdapter extends RecyclerView.Adapter<WallPaperAdapter.MyViewHolder>{
private List<WallpaperMain> wallpaperMains;
private Context context;
public WallPaperAdapter(List<WallpaperMain> wallpaperMains,Context context){
this.wallpaperMains =wallpaperMains;
this.context=context;
}
#Override
public WallPaperAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.wallpaper_item, null);
WallPaperAdapter.MyViewHolder viewHolder = new WallPaperAdapter.MyViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Glide.with(context)
.load("http://localhost:8080/api/motivation/wallpaper/large/37l")
.into(holder.waIlpapermageView);
// holder.waIlpapermageView.setImageResource(R.drawable.name);
}
#Override
public int getItemCount() {
return wallpaperMains.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
ImageView waIlpapermageView;
public MyViewHolder(View itemView) {
super(itemView);
waIlpapermageView =(ImageView) itemView.findViewById(R.id.wallpaperItem_imageView);
}
}
}
OUTPUT I am getting bellow
In your doInBackground method , instead of
wallpaperList = wallpaperMains;
use
wallpaperList.clear();
wallpaperList.addAll(wallpaperMains);
In onPostExecute()
#Override
protected void onPostExecute(JSONArray jsonArray) {
super.onPostExecute(jsonArray);
System.out.println(wallPaperAdapter);
wallPaperAdapter.notifyDataSetChanged();
System.out.println(wallpaperList.size());
}
Try this...
Please clear your Arraylist before adding the values wallpaperList.clear(); On onPreExecute() method.
recyclerView.setAdapter(wallPaperAdapter);
wallPaperAdapter.notifyDataSetChanged();
Whenever your ArrayList value is changing usenotifyDataSetChanged(); it will refresh your Recylierview
Related
I fetch the data from my Server with Volley and put the data inside a GridView.
Now when I use swipeToRefresh, it should load the new/changed data. For this I tried everything but nothing worked.
First my code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
List<getter_setter> list = new ArrayList<>();
grid_adapter grid_adapter;
GridView gridView;
SwipeRefreshLayout swipeRefreshLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipeRefreshLayout = findViewById(R.id.swipeRefresh);
getData();
gridView = findViewById(R.id.gridView);
grid_adapter = new grid_adapter(getApplicationContext(),list);
gridView.setAdapter(grid_adapter);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
getData();
grid_adapter.update(list);
swipeRefreshLayout.setRefreshing(false);
}
});
}
public void getData(){
final String url = "http://*.**.***.***/";
final RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("userdata");
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String NAME = jsonObject.getString("NAME");
String BILD = jsonObject.getString("VORSCHAUBILD");
getter_setter getter_setter = new getter_setter(NAME,"",BILD);
list.add(getter_setter);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonObjectRequest);
}
}
And the BaseAdapter
public class grid_adapter extends BaseAdapter{
Context context;
List<getter_setter> list;
public grid_adapter(Context context, List<getter_setter> list) {
this.context = context;
this.list = list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int i) {
return list.get(i);
}
#Override
public long getItemId(int i) {
return 0;
}
public void update(List<getter_setter> listUpdate){
this.list.addAll(listUpdate);
notifyDataSetChanged();
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
View gridView = view;
if(view == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
gridView = inflater.inflate(R.layout.grid_design,null);
}
final getter_setter getter = list.get(i);
TextView name = gridView.findViewById(R.id.NAME);
final ImageView bild = gridView.findViewById(R.id.bild);
name.setText(getter.getNAME());
Picasso.with(context).load(getter.getVORSCHAUBILD()).into(bild);
return gridView;
}
}
Check The Updated Listener
Explanation-:
Since You Are Passing Reference Of Your List Into RecyclerView Hence Updating List In The Activity Will Update The List In Adapter Automatically
No Need To Call update Method
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
list.clear(); // Clean The List Before Adding Updated Data
grid_adapter.notifyDataSetChanged();
getData();
grid_adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
});
I am using OkHttp to get HTML string and list the information in RecyclerView in a fragment.
However, when the app runs, it didn't show list information at first launch.
After I click other fragment page and go back to this fragment page, it show list.
But when I swipe down to see more list, the list repeat for twice (or more?) and the item background color disordered.
How can I fix it? Thanks!
My Adapter
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private List<NewsModel> mNewsList;
class ViewHolder extends RecyclerView.ViewHolder {
TextView newsNameText;
TextView newsDataText;
View listView;
public ViewHolder(View newsView) {
super(newsView);
newsNameText = (TextView) newsView.findViewById(R.id.news_Name);
newsDataText = (TextView) newsView.findViewById(R.id.news_Data);
listView = newsView;
}
}
public NewsAdapter(List<NewsModel> newsList) {
mNewsList = newsList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
return holder;
}
public void setData(List<NewsModel> viewData) {
mNewsList.clear();
mNewsList.addAll(viewData);
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
NewsModel news = mNewsList.get(position);
holder.setIsRecyclable(true);
if(position % 2 == 0){
holder.listView.setBackgroundColor(0x80E0EEEE);
}
holder.newsNameText.setText(news.getName());
holder.newsDataText.setText(news.getData());
}
#Override
public int getItemCount() {
return mNewsList.size();
}
}
My fragment
public class NewsFragment extends Fragment {
List<NewsModel> resultList = new ArrayList<>();
List<NewsModel> htmlList = new ArrayList<>();
NewsAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsView = inflater.inflate(R.layout.fragment_news, container, false);
RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsRecyclerView.setLayoutManager(layoutManager);
adapter = new NewsAdapter(getNews());
newsRecyclerView.setAdapter(adapter);
return newsView;
}
private List<NewsModel> getNews() {
new Thread(new Runnable() {
#Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
.build();
Response response = client.newCall(request).execute();
String resultString = response.body().string();
resultList.clear();
resultList.addAll(getResult(resultString));
adapter.notifyDataSetChanged();
/*new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
adapter.setData(resultList);
adapter.notifyDataSetChanged();
}
});//postdelayed (runnable long) cannot be applied to runnable*/
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
return resultList;
}
private List<NewsModel> getResult(final String response) {
XXXXXX
return htmlList;
}
}
The problem is that maybe you are adding many entries and since recyclerview is trying to reuse those views instead of redrawing again and again which cause sometimes view inconsistency. Here is the problem discussed Look into it if you are having the same problem.
to disable it or enable it to use in your bindViewHolder()
setIsRecyclable(Boolean enable)
And your second problem is that onCreateView() is called the second time when coming back from another fragment causing addition of duplicate data again so you need to clear the list before adding any new entries and Why it's not showing in the first run because you have added data in another thread and did not updated the adapter about it.
List<NewsModel> resultList = new ArrayList<>();
NewsAdapter adapter ;
public class NewsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsView = inflater.inflate(R.layout.fragment_news, container, false);
RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsRecyclerView.setLayoutManager(layoutManager);
adapter = new NewsAdapter(resultList);
newsRecyclerView.setAdapter(adapter);
getNews();
return newsView;
}
private void getNews(){
AsyncTask<Void,Void,String> asyncTask = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(final Void... voids) {
String resultString = null;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
.build();
Response response = null;
try {
response = client.newCall(request).execute();
resultString = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return resultString;
}
#Override
protected void onPostExecute(final String resultString) {
super.onPostExecute(resultString);
resultList.clear();
resultList.addAll(getResult(resultString));
adapter.notifyDataSetChanged();
}
}.execute();
}
The thread will change the resultList in some delay, but you already passed old data before that.
Please try as following...
public class NewsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsView = inflater.inflate(R.layout.fragment_news, container, false);
RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsRecyclerView.setLayoutManager(layoutManager);
getNews(newsRecyclerView);
return newsView;
}
private void getNews(final RecyclerView newsRecyclerView){
new Thread(new Runnable() {
#Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
.build();
Response response = client.newCall(request).execute();
String resultString = response.body().string();
List<NewsModel> resultList = getResult(resultString);
NewsAdapter adapter = new NewsAdapter(resultList);
newsRecyclerView.setAdapter(adapter);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private List<NewsModel> getResult(final String response) {
XXXXXXXXX
return List;
}
Main pattern is bad.
The easiest way for this code is to set (not add) items in adapter when it is downloaded and invoke on adapter notifyDataSetChanged() - all cells will be redraw.
So make adapter as field, add method to adapter setData() and:
...
Response response = client.newCall(request).execute();
String resultString = response.body().string();
resultList = getResult(resultString);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
adapter.setData(results);
adapter.notifyDataSetChanged();
}
});
I've a recyclerview adapter with 3 textviews. I used a model class to set texts. Now I want to use the same adapter with different layout and in a different class which only have 1 textview. When I tried, I got NullPointerException (may be becuz the other 2 textviews are blank). Is there any way to use same adapter with different layout and in different class?
// second class - I used 1 textview
public class Customers extends AppCompatActivity{
private CShowProgress cShowProgress;
private RecyclerView mRecyclerView;
private TimeLineAdapter mTimeLineAdapter;
private List<TimeLineModel> mDataList = new ArrayList<>();
private static final String CUSTOMERS = "http://192.168.200.3/ubooktoday/android/showspacustomerlist";
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.customers);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
cShowProgress = CShowProgress.getInstance();
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(getLinearLayoutManager());
mRecyclerView.setHasFixedSize(true);
showCustomers();
}
private void showCustomers() {
if(mDataList!=null )mDataList.clear();
cShowProgress.showProgress(Customers.this);
StringRequest stringRequest = new StringRequest(Request.Method.POST, CUSTOMERS,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
cShowProgress.hideProgress();
try {
JSONArray jsonArray = new JSONArray(response);
for(int i=0; i<jsonArray.length(); i++){
JSONObject obj = jsonArray.getJSONObject(i);
TimeLineModel model = new TimeLineModel();
model.setCustname(obj.getString("customername"));
mDataList.add(model);
mTimeLineAdapter = new TimeLineAdapter(getApplicationContext(), R.layout.item_row_customer, mDataList);
mRecyclerView.setAdapter(mTimeLineAdapter);
}
mTimeLineAdapter.notifyDataSetChanged();
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "VolleyError" + error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("spaid", "145");
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
}
private LinearLayoutManager getLinearLayoutManager() {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
return linearLayoutManager;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
break;
}
return true;
}
}
// first class - I used all 3 textviews
public class Walkin extends Fragment{
private RecyclerView mRecyclerView;
private TimeLineAdapter mTimeLineAdapter;
private List<TimeLineModel> mDataList = new ArrayList<>();
private static final String DASHBOARD = "My API";
#Nullable
#Override
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.walkin, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(getLinearLayoutManager());
mRecyclerView.setHasFixedSize(true);
showDashboard();
}
private void showDashboard() {
if(mDataList!=null )mDataList.clear();
cShowProgress.showProgress(getActivity());
StringRequest stringRequest = new StringRequest(Request.Method.POST, DASHBOARD,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("walkinlist");
for(int i=0; i<jsonArray.length(); i++){
JSONObject obj = jsonArray.getJSONObject(i);
TimeLineModel model = new TimeLineModel();
model.setCustname(obj.getString("customername"));
model.setTime(obj.getString("serviceDuration"));
model.setServname(obj.getString("service"));
mDataList.add(model);
mTimeLineAdapter = new TimeLineAdapter(getActivity(), R.layout.item_row_dashboard, mDataList);
mRecyclerView.setAdapter(mTimeLineAdapter);
}
mTimeLineAdapter.notifyDataSetChanged();
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "VolleyError" + error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("spaid", "145");
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(stringRequest);
}
private LinearLayoutManager getLinearLayoutManager() {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
return linearLayoutManager;
}
}
// Adapter class
public class TimeLineAdapter extends RecyclerView.Adapter<TimeLineViewHolder> {
private List<TimeLineModel> mFeedList;
int resource;
private Context mContext;
public TimeLineAdapter(Context mContext, int resource, List<TimeLineModel> feedList) {
this.resource = resource;
this.mContext = mContext;
mFeedList = feedList;
}
#Override
public TimeLineViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = View.inflate(parent.getContext(), resource, null);
return new TimeLineViewHolder(view, viewType);
}
#Override
public void onBindViewHolder(TimeLineViewHolder holder, int position) {
TimeLineModel timeLineModel = mFeedList.get(position);
holder.servicename.setText(timeLineModel.getServname());
holder.custname.setText(timeLineModel.getCustname());
holder.time.setText(timeLineModel.getTime());
}
#Override
public int getItemCount() {
return (mFeedList!=null? mFeedList.size():0);
}
}
// ViewHolder class
public class TimeLineViewHolder extends RecyclerView.ViewHolder {
public TextView servicename, custname, time;
public TimeLineViewHolder(View itemView, int viewType) {
super(itemView);
servicename = (TextView) itemView.findViewById(R.id.tv_service);
custname = (TextView) itemView.findViewById(R.id.tv_cust);
time = (TextView) itemView.findViewById(R.id.tv_time);
}
}
You can use the getItemViewType().
Make your adapter(here TimeLineAdapter) extend RecyclerView.Adapter only.
You can change the Adapter's constructer to recieve ItemType and use it in the getItemViewType
Override the int getItemViewType (int position) method in your adapter.
In the onCreateViewHolder you can differentiate between which layout you want to inflate by using the viewType parameter.
In onBindViewHolder use instanceof to check which ViewHolder was created and call the related bind functions
A Sample Code-
// Adapter class
public class TimeLineAdapter extends RecyclerView.Adapter{
.....
int type;
public TimeLineAdapter(Context mContext, int resource, List<TimeLineModel> feedList,int layoutType) {
.....
.....
type=layoutType;
}
#Override
public int getItemViewType(int position) {
return type;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType==1){
View view = View.inflate(parent.getContext(), resource, null);
return new TimeLineViewHolder(view, viewType);
}else{
View view = View.inflate(parent.getContext(), resource, null);
return new TimeLineViewHolder2(view, viewType);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(holder instanceof TimeLineViewHolder){
TimeLineModel timeLineModel = mFeedList.get(position);
((TimeLineViewHolder) holder).servicename.setText(timeLineModel.getServname());
......
}
else if(holder instanceof TimeLineViewHolder2){
....
....
}
}
#Override
public int getItemCount() {
return (mFeedList!=null? mFeedList.size():0);
}
}
when I conduct onRefresh, my recyclerView adds on another copy to my current recyclerView instead of refreshing it, by looking at my code below does anyone know what the problem is?I have tried everything but nothing seems to work?
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
//send our volley JSON Request
//Initialize VolleySingleton
mVolleySingleton = VolleySingleton.getInstance();
//intitalize Volley Singleton request key
mRequestQueue = mVolleySingleton.getRequestQueue();
//2 types of requests an Array request and an Object Request
JSONArrayRequest();
}
private void JSONArrayRequest() {
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, URL_API, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
listblogs=parseJSONResponse(response);
mAdapterDashBoard.setBloglist(listblogs);
System.out.println("it worked!!!");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ToastTest.t(getActivity(), error.toString());
}
});
mRequestQueue.add(request);
}
private ArrayList<Blogs> parseJSONResponse(JSONArray response) {
if (!response.equals("")) {
ArrayList<Blogs> blogsArrayList = new ArrayList<>();
try {
StringBuilder data = new StringBuilder();
for (int i = 0; i < response.length(); i++) {
JSONObject currentQuestions = response.getJSONObject(i);
String text = currentQuestions.getString("text");
String points = currentQuestions.getString("points");
String ID=currentQuestions.getString("id");
String courseId = currentQuestions.getString("courseId");
String studentId = currentQuestions.getString("studentId");
data.append(text + "\n" + points + "\n" + courseId + "\n");
System.out.println(data);
Blogs blogs = new Blogs();
blogs.setId(ID);
blogs.setMstudentId(studentId);
blogs.setMtext(text);
blogs.setPoints(points);
listblogs.add(blogs);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return listblogs;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate(R.layout.fragment_dashboard,container,false);
mRecyclerView=(RecyclerView)view.findViewById(R.id.fragment_dashboard);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mAdapterDashBoard=new AdapterDashBoard(getActivity());
mRecyclerView.setAdapter(mAdapterDashBoard);
mPullToRefreshView = (PullToRefreshView)view.findViewById(R.id.pull_to_refresh);
mPullToRefreshView.setOnRefreshListener(new PullToRefreshView.OnRefreshListener() {
#Override
public void onRefresh() {
mPullToRefreshView.postDelayed(new Runnable() {
#Override
public void run() {
mPullToRefreshView.setRefreshing(false);
JSONArrayRequest();
}
}, REFRESH_DELAY);
}
});
return view;
}
}
public class AdapterDashBoard extends RecyclerView.Adapter<AdapterDashBoard.ViewDashboard>{
private LayoutInflater mLayoutInflater;
private ArrayList<Blogs> listblogs=new ArrayList<>();
public AdapterDashBoard(Context context){
mLayoutInflater=LayoutInflater.from(context);
}
public void setBloglist(ArrayList<Blogs> listBlogs){
this.listblogs=listBlogs;
notifyItemRangeChanged(0,listBlogs.size());
}
#Override
public ViewDashboard onCreateViewHolder(ViewGroup parent, int viewType) {
View view= mLayoutInflater.inflate(R.layout.customizejson,parent,false);
ViewDashboard viewholder=new ViewDashboard(view);
return viewholder;
}
#Override
public void onBindViewHolder(ViewDashboard holder, int position) {
Blogs currentBlog=listblogs.get(position);
holder.questionText.setText(currentBlog.getMtext().toString());
holder.points.setText(currentBlog.getPoints().toString());
holder.id.setText(currentBlog.getId().toString());
}
#Override
public int getItemCount() {
return listblogs.size();
}
static class ViewDashboard extends RecyclerView.ViewHolder{
private ImageView thumbnail;
private TextView questionText;
private TextView points;
private TextView id;
public ViewDashboard (View itemView){
super(itemView);
//thumbnail=(ImageView)itemView.findViewById(R.id.thumbnail);
questionText=(TextView)itemView.findViewById(R.id.questionText);
points=(TextView)itemView.findViewById(R.id.points);
id=(TextView)itemView.findViewById(R.id.ID);
}
}
}
You need to clear your listblogs list before adding new items. This is why you get duplicated values.
Also you're already adding new items to listblogs in parseJSONResponse() method, so there is no need for listblogs=parseJSONResponse(response); in onResponse() method, while its the same list.
Change your onResponse() method to:
#Override
public void onResponse(JSONArray response) {
listblogs.clear(); // here you clear the old data
parseJSONResponse(response);
mAdapterDashBoard.setBloglist(listblogs);
System.out.println("it worked!!!");
}
I am newbie to Android apps development.
I have a class, which contains RecyclerView.
public class ScreenOne extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private RecyclerView mRecyclerView;
private FilmSetAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
SwipeRefreshLayout mSwipeRefreshLayout;
RequestTask requestTask;
ArrayList<Film> listOfFilms;
ArrayList<Cinema> listOfCinemas;
ArrayList<String> cityIDs;
public ScreenOne() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.screen_one, container,
false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(getActivity());
//mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManager);
//mRecyclerView.setItemAnimator(new DefaultItemAnimator());
listOfFilms = new ArrayList<>();
mAdapter = new FilmSetAdapter(listOfFilms);
mRecyclerView.setAdapter(mAdapter);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorScheme(R.color.blue, R.color.cyan, R.color.grey_blue, R.color.lightblue);
try {
updateFilms();
} catch (InterruptedException e) {
e.printStackTrace();
}
return rootView;
}
private void updateFilms() throws InterruptedException {
requestTask = new RequestTask();
try {
requestTask.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
private boolean isNetworkConnected() {
ConnectivityManager cm =
(ConnectivityManager) getActivity().getSystemService(getActivity().CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
#Override
public void onRefresh() {
Toast.makeText(getActivity(), R.string.refresh_started, Toast.LENGTH_SHORT).show();
mSwipeRefreshLayout.setRefreshing(true);
mAdapter.setDataset(new ArrayList<Film>());
mAdapter.notifyDataSetChanged();
try {
updateFilms();
} catch (InterruptedException e) {
e.printStackTrace();
}
DatabaseHandler database = new DatabaseHandler(getActivity());
mAdapter = new FilmSetAdapter(database.getAllFilms());
mRecyclerView.swapAdapter(mAdapter, false);
database.close();
mSwipeRefreshLayout.postDelayed(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(getActivity(), R.string.refresh_finished, Toast.LENGTH_SHORT).show();
}
}, 3000);
}
class RequestTask extends AsyncTask<Void, Void, Void> {
protected void getPreferenciesCity()
{
cityIDs = new ArrayList<>();
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
Set<String> selections = sharedPrefs.getStringSet("cities", null);
try {
Log.d("SHARED PREFERENCES CITY", selections.toString());
cityIDs.addAll(selections);
}catch (NullPointerException e){Log.d("SHARED PREFERENCES CITY", "SP are empty");}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
listOfFilms = new ArrayList<>();
getPreferenciesCity();
}
#Override
protected Void doInBackground(Void... params) {
if(isNetworkConnected()) {
DatabaseHandler database = new DatabaseHandler(getActivity());
database.clearFilms();
try {
HttpHandler httpHandler = new HttpHandler();
listOfFilms = new ArrayList<>(httpHandler.listOfFilmsRequest(cityIDs));
listOfCinemas = new ArrayList<>(httpHandler.listOfCinemasRequest());
Film film;
Cinema cinema;
for (Iterator<Film> filmiterator = listOfFilms.iterator(); filmiterator.hasNext(); ) {
film = filmiterator.next();
if (database.isInDatabase(film.getID()))
database.updateFilm(film);
else
database.addFilm(film);
}
for (Iterator<Cinema> cinemaiterator = listOfCinemas.iterator(); cinemaiterator.hasNext(); ) {
cinema = cinemaiterator.next();
if (database.CinemaIsInDatabase(cinema.getIDCinema()))
database.updateCinema(cinema);
else
database.addCinema(cinema);
}
database.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
DatabaseHandler database = new DatabaseHandler(getActivity());
mAdapter.setDataset(database.getAllFilms());
mAdapter.notifyDataSetChanged();
}
}
}
It executes a method, which is placed in the AsyncTask class. This method downloads data from server, puts it to database first and after that sets the recycler view adapter. The problem is that sometimes text data are changed while scrolling it. See attached video.
Code of adapter is:
public class FilmSetAdapter extends RecyclerView.Adapter<FilmSetAdapter.ViewHolder>{
private ArrayList<Film> mDataset;
final static String LOG_TAG = "FilmSetAdapter";
public void setDataset(ArrayList<Film> allFilms) {
mDataset = new ArrayList<>(allFilms);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public static TextView filmTitle;
public TextView country;
public TextView ticketsFrom;
public TextView rating;
public TextView format;
public ImageView poster;
public int id;
public ViewHolder(final View itemView) {
super(itemView);
filmTitle = (TextView) itemView.findViewById(R.id.filmtitle);
country = (TextView)itemView.findViewById(R.id.country);
ticketsFrom = (TextView) itemView.findViewById(R.id.ticketsfrom);
rating = (TextView)itemView.findViewById(R.id.rating);
poster = (ImageView) itemView.findViewById(R.id.poster);
format = (TextView) itemView.findViewById(R.id.format);
format.setTypeface(null, Typeface.BOLD_ITALIC);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cardview, parent, false);
final ViewHolder vh = new ViewHolder(v);
v.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
Log.d(LOG_TAG, "Нажата карточка. Вызов из activity "+v.toString());
Intent intent = new Intent(v.getContext(),FilmInfoActivity.class);
intent.putExtra("EXTRA_FILM_ID", vh.id);
v.getContext().startActivity(intent);
}
});
return vh;
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.filmTitle.setText(mDataset.get(position).getTitle().toString()+" ID="+mDataset.get(position).getID()+" POS="+position);
holder.country.setText(mDataset.get(position).getCountry());
holder.ticketsFrom.setText(holder.ticketsFrom.getContext().getString(R.string.tickets_from) +
mDataset.get(position).getRating().toString());
holder.rating.setText(holder.rating.getContext().getString(R.string.rating_kinopoisk) +
mDataset.get(position).getRating());
holder.id = mDataset.get(position).getID();
holder.format.setText(mDataset.get(position).getFormat());
Picasso.with(holder.poster.getContext()).
load(mDataset.get(position).getPoster()).
skipMemoryCache().
into(holder.poster);
}
#Override
public int getItemCount() {
if(mDataset != null)
return mDataset.size();
return 0;
}
public FilmSetAdapter(ArrayList<Film> myDataset) {
mDataset = new ArrayList<>(myDataset);
}
}
I have no clue on how to sort it out.
it seem to that there is a typo mistake in your code, look at that, you have in your ViewHolder:
public static TextView filmTitle;
But then you work with it like with your other fields:
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.filmTitle.setText(mDataset.get(position).getTitle() + ...);
...
}
A little advice for you as a newbie: just.. pay more attention to your code, and you'll be fine in programming :)