SwipeRefreshLyout not Working Properly - android

So I have Fragment that is supposed to fetch some data from Internet using RecyclerView i want to add the Swipe Refresh Gesture to my Fragment so the user can check out if any new piece of data is on .
Here is my code :
Fragment :
public class HomeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
public HomeFragment() {
// Required empty public constructor
}
RecyclerView recyclerView;
SwipeRefreshLayout swipeRefreshLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
swipeRefreshLayout=(SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);
recyclerView = (RecyclerView) view.findViewById(R.id.recylerview);
ReadRss readRss = new ReadRss(getContext(), recyclerView);
readRss.execute();
return view;
}
#Override
public void onRefresh() {
new ReadRss(getContext(), recyclerView).execute();
if(swipeRefreshLayout.isRefreshing())swipeRefreshLayout.setRefreshing(false);
}
}
XML Layout :
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/swipeRefreshLayout"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.essat.essat.HomeFragment"
>
<!-- TODO: Update blank fragment layout -->
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/recylerview"
/>
>
</android.support.v4.widget.SwipeRefreshLayout>
The Problem is that the SwipeRefreshLayout never stops turning even with this piece of code :
if(swipeRefreshLayout.isRefreshing())swipeRefreshLayout.setRefreshing(false);
I Hope someone knows how to fix this , Thank You :)
UPDATE :
public class ReadRss extends AsyncTask<Void, Void, Void> {
Context context;
String address = "http://www.sciencemag.org/rss/news_current.xml";
ProgressDialog progressDialog;
URL url;
ArrayList<FeedItem>feedItems;
RecyclerView recyclerView;
public ReadRss(Context context,RecyclerView recyclerView ) {
this.recyclerView=recyclerView;
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
}
#Override
protected void onPreExecute() {
progressDialog.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
((IWithHttpRequest) context).onDataUpdate();
Adapter adapter = new Adapter(context, feedItems);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new VerticalSpace(20));
recyclerView.setAdapter(adapter);
}
#Override
protected Void doInBackground(Void... params) {
ProcessXml(Getdata());
return null;
}
private void ProcessXml(Document data) {
if (data != null) {
feedItems=new ArrayList<>();
Element root = data.getDocumentElement();
Node channel = root.getChildNodes().item(1);
NodeList items = channel.getChildNodes();
for (int i = 0; i < items.getLength(); i++) {
Node cureentchild = items.item(i);
if (cureentchild.getNodeName().equalsIgnoreCase("item")) {
FeedItem item=new FeedItem();
NodeList itemchilds = cureentchild.getChildNodes();
for (int j = 0; j < itemchilds.getLength(); j++) {
Node cureent = itemchilds.item(j);
if (cureent.getNodeName().equalsIgnoreCase("title")){
item.setTitle(cureent.getTextContent());
}else if (cureent.getNodeName().equalsIgnoreCase("description")){
item.setDescription(cureent.getTextContent());
}else if (cureent.getNodeName().equalsIgnoreCase("pubDate")){
item.setPubDate(cureent.getTextContent());
}else if (cureent.getNodeName().equalsIgnoreCase("link")){
item.setLink(cureent.getTextContent());
}else if (cureent.getNodeName().equalsIgnoreCase("media:thumbnail")) {
String url = cureent.getAttributes().item(0).getTextContent();
item.setThumbnailUrl(url);
}
}
feedItems.add(item);
}
}
}
}
public Document Getdata() {
try {
url = new URL(address);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDoc = builder.parse(inputStream);
return xmlDoc;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Fragment Updated :
public class HomeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,IWithHttpRequest{
public HomeFragment() {
// Required empty public constructor
}
RecyclerView recyclerView;
SwipeRefreshLayout swipeRefreshLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
swipeRefreshLayout=(SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setOnRefreshListener(this);
recyclerView = (RecyclerView) view.findViewById(R.id.recylerview);
ReadRss readRss = new ReadRss(getContext(), recyclerView);
readRss.execute();
return view;
}
#Override
public void onRefresh() {
new ReadRss(getContext(), recyclerView).execute();
}
#Override
public void onDataUpdate() {
swipeRefreshLayout.setRefreshing(false);
}
}

You forgot this in onCreateView
swipeRefreshLayout.setOnRefreshListener(this);
Also, new ReadRss(getContext(), recyclerView).execute(); is asynchronous, or at least should be (don't block the UI thread), so the it will look like the refresh is instantaneous.
The best solution here should be to create an interface
public interface IWithHttpRequest {
void onDataUpdate()
}
Make your activity implement IWithHttpRequest
public class HomeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, IWithHttpRequest {
...
#Override
public void onDataUpdate() {
swipeRefreshLayout.setRefreshing(false);
}
}
and in ReadRss, when you finished fetching data call
((IWithHttpRequest) context).onDataUpdate()

in order to refresh you should do this :
mSwipeRefreshLayout = (SwipeRefreshLayout) myFragmentView.findViewById(R.id.refreshContainer);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// refresh logic
if (mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}
}
You may also try to clear your data in recyclerview like this
YourAdapter.clearData();

You need to set setOnRefreshListener for the swipeRefreshLayout.
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setOnRefreshListener(this);

Related

Volley, SwipeToRefresh and notifyDataSetChanged() not working

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);
}
});

Synchronous Call in Fragment didn't run at first launch and get error data

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();
}
});

Fragment recyclerView adapter notifyDataSetChanged() from MainActivity

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

Pull to refresh recyclerview android

Hi I've a tabbed activity, and in the first tab I fetch data from server and show it in a recyclerview within card views. For fetching the data from server I use the volley library. I want to implement the Pull to refresh to load the data (so whenever I pull it has to do the request to the network). And I want also to disable the network request whenever I switch between tabs (because when I change tab focus in my app it starts to fetching data) I want to do the network request only 1 time (when user log in first time) and then others requests maneged only by pull to refresh.
Here's my fragment where I've recyclerview and show the data:
public class Tab1History extends Fragment
{
private RecyclerView recyclerView;
private CespiteAdapter adapter;
UserSessionManager session;
private static final String URL_DATA = "http://mydata.php";
private List<CespiteOgg> cespiteOggList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.tab1history, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);//every item of the RecyclerView has a fix size
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
cespiteOggList = new ArrayList<>();
loadRecyclerViewData();
return rootView;
}
private void loadRecyclerViewData()
{
// Session class instance
session = new UserSessionManager(getActivity());
//get user data from session
HashMap<String, String> user = session.getUserDetails();
//get name
String name = user.get(UserSessionManager.KEY_NAME);
// get username
final String usernameUtente = user.get(UserSessionManager.KEY_USERNAME);
final ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Carimento dati...");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST,
URL_DATA,
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
progressDialog.dismiss();
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray array = jsonObject.getJSONArray("dates");
for(int i=0; i<array.length(); i++)
{
JSONObject o = array.getJSONObject(i);
CespiteOgg item = new CespiteOgg(
o.getString("CodNumInventario"),
o.getString("Nome"),
o.getString("DtCatalogazione"),
o.getString("CodIdA"),
o.getString("username")
);
cespiteOggList.add(item);
}
adapter = new CespiteAdapter(cespiteOggList, getActivity());
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Username", usernameUtente);
return params;
}
};
RegisterRequest.getmInstance(getActivity()).addToRequestque(stringRequest);
}
}
And it's the adapter:
public class CespiteAdapter extends RecyclerView.Adapter<CespiteAdapter.ViewHolder>
{
private List<CespiteOgg> cespiteOggList;
private Context context;
public CespiteAdapter(List<CespiteOgg> cespiteOggList, Context context) {
this.cespiteOggList = cespiteOggList;
this.context = context;
}
public class ViewHolder extends RecyclerView.ViewHolder
{
public CardView cv;
public TextView txtNumInventario;
public TextView txtNomeCespite;
public TextView txtDtCatalogazione;
public TextView txtAula;
public TextView txtNomeUser;
ViewHolder(View itemView)
{
super (itemView);
//cv = (CardView) itemView.findViewById(R.id.cardView);
txtNumInventario = (TextView) itemView.findViewById(R.id.txtNumeroInventario);
txtNomeCespite = (TextView) itemView.findViewById(R.id.txtNomeCespite);
txtDtCatalogazione = (TextView) itemView.findViewById(R.id.txtDataCatalogazione);
txtAula = (TextView) itemView.findViewById(R.id.txtAula);
txtNomeUser= (TextView) itemView.findViewById(R.id.txtNomeUser);
}
}
#Override
public CespiteAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View cespiteView = inflater.inflate(R.layout.cespite_card_view, parent, false);
return new ViewHolder(cespiteView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
CespiteOgg cespiteOgg = cespiteOggList.get(position);
holder.txtNumInventario.setText(cespiteOgg.getNumInventario());
holder.txtNomeCespite.setText(cespiteOgg.getNomeCespite());
holder.txtDtCatalogazione.setText(cespiteOgg.getDtCatalogazione());
holder.txtAula.setText(cespiteOgg.getAula());
holder.txtNomeUser.setText(cespiteOgg.getNomeUser());
}
#Override
public int getItemCount()
{
return cespiteOggList.size();
}
}
You can use android SwipeRefreshLayout widget instead of ProgressDialog.
Follow below steps to integrate SwipeRefreshLayout in your Tab1history fragment:
1. In your layout tab1history, add SwipeRefreshLayout as a root layout and place RecyclewrView inside it.
// tab1history.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
2. In your Tab1History fragment, use SwipeRefreshLayout as below to load data from server:
// Tab1History.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.StringRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class Tab1History extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
SwipeRefreshLayout mSwipeRefreshLayout;
private RecyclerView recyclerView;
private CespiteAdapter adapter;
UserSessionManager session;
private static final String URL_DATA = "http://mydata.php";
private List<CespiteOgg> cespiteOggList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.tab1history, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);//every item of the RecyclerView has a fix size
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
cespiteOggList = new ArrayList<>();
// SwipeRefreshLayout
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary,
android.R.color.holo_green_dark,
android.R.color.holo_orange_dark,
android.R.color.holo_blue_dark);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
mSwipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
// Fetching data from server
loadRecyclerViewData();
}
});
return rootView;
}
/**
* This method is called when swipe refresh is pulled down
*/
#Override
public void onRefresh() {
// Fetching data from server
loadRecyclerViewData();
}
private void loadRecyclerViewData()
{
// Showing refresh animation before making http call
mSwipeRefreshLayout.setRefreshing(true);
// Session class instance
session = new UserSessionManager(getActivity());
//get user data from session
HashMap<String, String> user = session.getUserDetails();
//get name
String name = user.get(UserSessionManager.KEY_NAME);
// get username
final String usernameUtente = user.get(UserSessionManager.KEY_USERNAME);
StringRequest stringRequest = new StringRequest(Request.Method.POST,
URL_DATA,
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray array = jsonObject.getJSONArray("dates");
for(int i=0; i<array.length(); i++)
{
JSONObject o = array.getJSONObject(i);
CespiteOgg item = new CespiteOgg(
o.getString("CodNumInventario"),
o.getString("Nome"),
o.getString("DtCatalogazione"),
o.getString("CodIdA"),
o.getString("username")
);
cespiteOggList.add(item);
}
adapter = new CespiteAdapter(cespiteOggList, getActivity());
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
// Stopping swipe refresh
mSwipeRefreshLayout.setRefreshing(false);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Stopping swipe refresh
mSwipeRefreshLayout.setRefreshing(false);
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Username", usernameUtente);
return params;
}
};
RegisterRequest.getmInstance(getActivity()).addToRequestque(stringRequest);
}
}
Hope this will work properly.
XML code
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/layout_titlebar">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/layout_titlebar"
android:layout_margin="5dp"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
Java code
public class BooksActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
SwipeRefreshLayout swipLayout;
RecyclerView recyclerview;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
recyclerview = view.findViewById(R.id.recyclerview);
swipLayout = view.findViewById(R.id.swipe_layout);
swipLayout.setOnRefreshListener(this);
}//end of onCreate
#Override
public void onRefresh() {
//your refresh code here
loadRecyclerViewData()
}
private void loadRecyclerViewData(){
onSuccess(){
//don't forget to stop refreshing
swipLayout.setRefreshing(false);
}
onFaliure(){
//don't forget to stop refreshing
swipLayout.setRefreshing(false);
}
}
}
Source Code
https://drive.google.com/open?id=1qjJ_to-1knVNaJB4T3U_L_p_YYNvgAeZ
APK
https://drive.google.com/open?id=1MxQZwjIXgR2jgDkUW1mbFrTLMSaQQisC
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
SwipeRefreshLayout mSwipeRefreshLayout;
// SwipeRefreshLayout
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setOnRefreshListener(this);
// mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary,
mSwipeRefreshLayout.setColorSchemeResources(R.color.colorAccent,
android.R.color.holo_green_dark,
android.R.color.holo_orange_dark,
android.R.color.holo_blue_dark);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
mSwipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
if(mSwipeRefreshLayout != null) {
mSwipeRefreshLayout.setRefreshing(true);
}
// TODO Fetching data from server
fetchContacts();
}
});
#Override
public void onRefresh() {
fetchContacts();
}
Android has a SwipeToRefresh widget to do this.
This question has been answered before here how-to-implement-pull-down-refresh-in-android and how-to-implement-android-pull-to-refresh
Pull To Refresh ListView & RecyclerView Example In Android Studio – SwipeRefreshLayout.I Hope this code work properly you can try this code.
Basic Pull To Refresh / SwipeRefreshLayout XML code:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/simpleSwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
< Add View's Here..../>
</android.support.v4.widget.SwipeRefreshLayout>
Below you can download code, see final output and step by step explanation of the basic Pull To refresh example. get full code with example https://abhiandroid.com/materialdesign/pulltorefresh
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
SwipeRefreshLayout swipeLayout;
//Getting SwipeContainerLayout
swipeLayout = findViewById(R.id.swipe_container);;
//swip listener
swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
loadData();
swipeLayout.setRefreshing(false);
}
});
}
With no using SwipeRefreshLayout. For example, if you want to fetch data from internet when your RecyclerView is already scrolled up/down completely (your top item is visible) and you are trying to scroll more. If, in that case, you wanna call getListItems from net:
itemsRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
int scrolling = 0;
int scrollingOnPrevIdleState = 0; // -1 or less prevents call getItemList() on first try
#Override
public void onScrollStateChanged(RecyclerView rv, int newState) {
super.onScrollStateChanged(rv, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (scrolling == scrollingOnPrevIdleState) {
myViewModel.getItemList();
// HERE IS THE PLACE where your refreshing data method is being called
}
scrollingOnPrevIdleState = scrolling;
}
}
#Override
public void onScrolled(RecyclerView rv, int dx, int dy) {
super.onScrolled(rv, dx, dy);
scrolling += Math.abs(dy);
}
});

how to send ArrayList(Bitmap) from asyncTask to Fragment and use it in Arrayadapter

I want to send a list of bitmap i retreived from mysql database using asyncTask to the fragment Fragment_ListView.class, in this fragment class i want to set the adapter of the listView with the bitmap token from asyncTask but i don't know how to do that.
Async Task
#Override
protected void onPostExecute(ArrayList<Bitmap> bitmapArrayList) {
super.onPostExecute(bitmapArrayList);
loading.dismiss();
// now after getting images from server , i want to send this bitmapArrayList
// to Fragment_ListView where i set the adapter of the
}
#Override
protected ArrayList<Bitmap> doInBackground(String... params) {
imageList = new ArrayList();
String add1 = "http://192.168.1.11/save/load_image_from_db.php?id=1";
String add2 = "http://192.168.1.11/save/load_image_from_db.php?id=2";
String add3 = "http://192.168.1.11/save/load_image_from_db.php?id=3";
URL url;
Bitmap image = null;
String[] adds = {add1, add2, add3};
for (int i = 0; i < adds.length; i++) {
try {
url = new URL(adds[i]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
image = BitmapFactory.decodeStream(connection.getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
imageList.add(image);
image = null;
}
return imageList;
OnCreate of MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listfrg = new Fragment_ListView();
getFragmentManager().beginTransaction().add(R.id.frml, listfrg).commit();
}
Fragment_ListView :
public class Fragment_ListView extends Fragment {
ListView mListView;
static ArrayList<Bitmap> bitmaps;
static MySimpleArrayAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frglist, container, false);
mListView = (ListView) view.findViewById(R.id.listView);
bitmaps = new ArrayList<>();
adapter = new MySimpleArrayAdapter(getActivity(), bitmaps);
mListView.setAdapter(adapter);
return view;
}
Something like this,
Create a new interface file
public interface BitMapArrayCallBack {
abstract void bitmapArray(ArrayList<Bitmap> bitmaps);
}
Then in AsyncTask ... i don't know your class name so i will assume the class ServerRequest
public class ServerRequest {
Context context;
public ServerRequest(Context context) {
this.context = context;
}
public void doAsyncTask(BitMapArrayCallBack bitmapCallback) {
new MyAsyncTask(bitmapCallback).execute();
}
public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
private BitMapArrayCallBack bitmapCallback;
public MyAsyncTask(BitMapArrayCallBack bitmapCallback) {
this.bitmapCallback = bitmapCallback;
}
//call do in background etc..
#Override
protected void onPostExecute(ArrayList<Bitmap> bitmapArrayList) {
super.onPostExecute(bitmapArrayList);
loading.dismiss();
bitmapCallback.bitmapArray(bitmapArrayList);
// This will hold and return your arraylist
}
}
}
Now you must call your asynctask in fragment listview
public class Fragment_ListView extends Fragment {
ListView mListView;
static MySimpleArrayAdapter adapter;
private ServerRequest serverRequest;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frglist, container, false);
mListView = (ListView) view.findViewById(R.id.listView);
serverRequest = new ServerRequest(getActivity);
serverRequest.doAsyncTask(new BitMapArrayCallBack {
#Override
void bitMapArray(ArrayList<Bitmap> bitmaps) {
// in here you have access to the bitmaps array
adapter = new MySimpleArrayAdapter(getActivity(), bitmaps);
mListView.setAdapter(adapter);
}
})
return view;
}

Categories

Resources