BaseAdapter crashes on notifyDataSetChanged update? - java

When trying to update my array adapter upon a network request, the program crashes with Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference, I have seen other posts with the same time but every method I try seems to just result in an error, the same crashing bug most likely.
Of course the title says, I am using notifyDataSetChanged() to update my lists.
Here is my code that I am using
import android.app.DownloadManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MyActivity";
public ArrayList<String> aContacts = new ArrayList<String>();
public ListView contacts;
public CustomAdapter customAdapter;
// User Setup Defaults
String server = "https://xxxxxxxx";
String suser = "xxxxxx";
String spass = "xxxxxx";
String sreq;
public void getContacts() {
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url = server+"/xxxxxx/?username="+suser+"&password="+spass+"&getcontacts=yes";
StringRequest stringRequest = new StringRequest(com.android.volley.Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
Log.v(TAG, "I recieved: " + response);
try {
JSONArray parseContacts = new JSONArray(response);
for (int x = 0; x < parseContacts.length(); x++) {
JSONArray array = (JSONArray) parseContacts.get(x);
for (int j = 0; j < array.length(); j++){
// print: array.get(j).toString();
}
aContacts.add(array.get(0).toString());
customAdapter.notifyDataSetChanged(); // ERROR IS HERE
}
}catch(JSONException e) {
Log.v(TAG, "Error: "+e);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.v(TAG, "Oops, an error occurred");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ListView contacts = (ListView)findViewById(R.id.contacts);
getContacts();
CustomAdapter customAdapter = new CustomAdapter();
contacts.setAdapter(customAdapter);
contacts.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object o = contacts.getItemAtPosition(position);
Toast.makeText(getBaseContext(),aContacts.get(position),Toast.LENGTH_SHORT).show();
}
});
}
class CustomAdapter extends BaseAdapter {
#Override
public int getCount() {
return aContacts.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.row,null);
TextView username = (TextView) convertView.findViewById(R.id.username);
username.setText(aContacts.get(position));
return convertView;
}
}
}
Im trying to parse JSON data and that works fine, and I add the results to an array and it would appear something like this {"one", "two", "three"}, but it doesnt seem to have to do with that and just crashes with that error on runtime. I have struggled at this forever now, if someone could give me some code that is the working version would be really nice but probably wouldnt happen, so just reference the issue please, or whatever you can do to help, thanks!

Related

Hide RecyclerView until List is sorted

When my RecyclerView loads it shows the unsorted list for a few milliseconds and then switches to the sorted list.
Here is a video what it looks like: https://drive.google.com/file/d/14UnS54S9JNp9VPYxIOAHIiPnJjksdYOL/view
Does anyone know how i can fix this?
Thanks in advance!
This is my code:
package com.example.thecryptoapp11;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.SystemClock;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
public class Fragment_Track extends Fragment {
View view;
private EditText searchEDT;
private RecyclerView currenciesRV;
private ArrayList<TrackRVModal> currencyRVModalArrayList;
private TrackRVAdapter currencyRVAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_track, container, false);
searchEDT = (EditText) view.findViewById(R.id.idEdtSearch);
currenciesRV = (RecyclerView) view.findViewById(R.id.idRVCurrencies);
RecyclerView.LayoutManager recyce = new LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false);
currenciesRV.setLayoutManager(recyce);
currencyRVModalArrayList = new ArrayList<>();
currencyRVAdapter = new TrackRVAdapter(currencyRVModalArrayList, requireContext());
currenciesRV.setAdapter(currencyRVAdapter);
getCurrencyDataPage();
searchEDT.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
filterCurrencies(editable.toString());
}
});
return view;
}
private void filterCurrencies(String currency) {
ArrayList<TrackRVModal> filteredList = new ArrayList<>();
for (TrackRVModal item : currencyRVModalArrayList) {
if (item.getName().toLowerCase().contains(currency.toLowerCase())) {
filteredList.add(item);
}
}
if (filteredList.isEmpty()) {
//Toast.makeText(requireContext(), "No Currency found...", Toast.LENGTH_SHORT).show();
} else {
currencyRVAdapter.filterList(filteredList);
}
}
private void getCurrencyDataPage() {
for(int i=1; i<=3; i++) {
String url = "https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&order=market_cap_desc&per_page=250&page="+i+"&sparkline=false";
RequestQueue requestQueue = Volley.newRequestQueue(requireContext());
int finalI = i;
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
for (int i = 0; i < response.length(); i++) {
// Get current json object
JSONObject currency = response.getJSONObject(i);
String name = currency.getString("name");
String symbol = currency.getString("symbol").toUpperCase();
String image_url = currency.getString("image");
int ID = currency.getInt("market_cap_rank");
double price = currency.getDouble("current_price");
currencyRVModalArrayList.add(new TrackRVModal(name, symbol, price, ID, image_url));
}
Collections.sort(currencyRVModalArrayList, TrackRVModal.TrackRVModalIDComparator);
currencyRVAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(requireContext(), "Error", Toast.LENGTH_SHORT).show();
}
});
requestQueue.add(jsonArrayRequest);
}
}
}
The Comparator:
public static Comparator<TrackRVModal> TrackRVModalIDComparator = new Comparator<TrackRVModal>() {
#Override
public int compare(TrackRVModal currency1, TrackRVModal currency2) {
return currency1.getID() - currency2.getID();
}
};

Unable to refresh the updated data after clicking on search button (Fetching data via API)

I am not able to update the values when i click on the search button, The data is fetched but the old fetched data is not getting discards, the fetched data is overlapping over each other
SearchFragment.java
package com.example.recipeappandroid.Fragments;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.example.recipeappandroid.Adapter.RecipeAdapter;
import com.example.recipeappandroid.Model.Recipe;
import com.example.recipeappandroid.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class SearchFragment extends Fragment {
Button click;
//public static TextView fetchedText;
ImageView searching_logo;
TextView searching_text;
SearchView searchbar;
String query="";
RecyclerView recyclerView;
public static ArrayList<Recipe> recipeList;
public static RecipeAdapter recipeAdapter;
private RequestQueue mRequestQueue;
private String Api_id= "3f335994";
private String Api_key = "8e99e327d1f2130dc6ab3422e26a95e8";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_search, container, false);
click = (Button) view.findViewById(R.id.button1);
//fetchedText = (TextView) view.findViewById(R.id.fetcheddata);
searchbar = (SearchView) view.findViewById(R.id.searchbar);
searching_logo = view.findViewById(R.id.searching_logo);
searching_text = view.findViewById(R.id.searching_text);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
//recipeAdapter = new RecipeAdapter();
recipeList = new ArrayList<>();
//getData();
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
query = searchbar.getQuery().toString();
String url = "https://api.edamam.com/search?q=" + query + "&app_id=" + Api_id + "&app_key=" + Api_key;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url,null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray hits = response.getJSONArray("hits");
for (int i =0;i<hits.length();i++) {
JSONObject jsonObject = hits.getJSONObject(i);
JSONObject recipe = jsonObject.getJSONObject("recipe");
String recipe_img = recipe.getString("image");
String recipe_title = recipe.getString("label");
String recipe_data = recipe.getString("source");
recipeList.add(new Recipe(recipe_img,recipe_title,recipe_data));
}
recipeAdapter = new RecipeAdapter(getContext(),recipeList);
recyclerView.setAdapter(recipeAdapter);
recipeAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue = Volley.newRequestQueue(getContext());
mRequestQueue.add(jsonObjectRequest);
/*JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
for (int i = 0; i < response.length(); i++) {
JSONObject jsonObject = response.getJSONObject(i);
JSONObject recipes = jsonObject.getJSONObject("recipe");
//Recipe recipe = new Recipe();
String recipe_img = recipes.getString("image");
String recipe_title = recipes.getString("label");
String recipe_data = recipes.getString("source");
recipeList.add(new Recipe(recipe_img,recipe_title,recipe_data));
Log.d("data",recipe_title);
}
//recipeAdapter = new RecipeAdapter(getContext(), recipeList);
//recyclerView.setAdapter(recipeAdapter);
recipeAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Toast.makeText(SearchFragment.this,"Error Occured",Toast.LENGTH_SHORT).show();
error.printStackTrace();
}
});*/
/*jsonArrayRequest.setRetryPolicy(new RetryPolicy() {
#Override
public int getCurrentTimeout() {
return 3000;
}
#Override
public int getCurrentRetryCount() {
return 3000;
}
#Override
public void retry(VolleyError error) throws VolleyError {
}
});*/
/* Log.d("QUEEEERRRYYYY",query);
ApiCall process = new ApiCall(searching_logo,searching_text);
process.execute(query);*/
}
});
return view;
}
}
I want to get rid of the old data after the new data is fetched and don't want to display it after the new one is called
looks like you are only adding items to your ArrayList<Recipe> recipeList;, so they may duplicate
maybe try to recipeList.clear(); it in first line of onResponse method
also notifyDataSetChanged isn't needed, setAdapter does it itself (and a lot more in fact)

Android Post values from Recyclerview Checkbox to database

I'm working on an employee attendance attendance applicaion, for that I'm listing employee namelist from my MySQL database to android RecyclerView. Everything is working fine. But what I actually wanted is, I want to update my attendance table with the CheckBox values, my table contains 3 columns id,emp_id,emp_attn, If the checkbox is checked for an employee, the app should post it as checked ! So how can i identify each checkbox in my recyclerview,
MyAdapter.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
/**
* Created by Akshay N Shaju on 10/20/2017.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private List<Listitems> listitemses;
private Context context;
public MyAdapter(List<Listitems> listitemses, Context context) {
this.listitemses = listitemses;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Listitems listitem = listitemses.get(position);
holder.CbHead.setText(listitem.getHead());
holder.textViewDesc.setText(listitem.getDesc());
holder.CbHead.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,listitem.getHead(), Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return listitemses.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public CheckBox CbHead;
public TextView textViewDesc;
public LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
CbHead = (CheckBox) itemView.findViewById(R.id.CbHead);
textViewDesc = (TextView) itemView.findViewById(R.id.textViewDisc);
linearLayout = (LinearLayout) itemView.findViewById(R.id.LinearLyout1);
}
}
}
MainActivity.java
import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String URL_DATA = "https://xxxxxxx.com/sample.json";
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private List<Listitems> listitemses;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
listitemses = new ArrayList<>();
loadRecyclerViewData();
}
private void loadRecyclerViewData(){
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading Data");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.GET,
URL_DATA,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("employee");
for(int i=0; i<array.length(); i++){
JSONObject o = array.getJSONObject(i);
Listitems item = new Listitems(
o.getString("name"),
o.getString("id"),
o.getString("image")
);
listitemses.add(item);
}
adapter = new MyAdapter(listitemses,getApplicationContext());
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(getApplicationContext(),"error",Toast.LENGTH_SHORT).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
ListItems.java
/**
* Created by Akshay N Shaju on 10/20/2017.
*/
public class Listitems {
private String head;
private String desc;
private String imageurl;
public Listitems(String head, String desc, String imageurl) {
this.head = head;
this.desc = desc;
this.imageurl = imageurl;
}
public String getHead() {
return head;
}
public String getDesc() {
return desc;
}
public String getImageurl() {
return imageurl;
}
}
Here in my adapter I tried an onClick Listner, which toast the employee name when checked and it worked ! but how can I get all the checkbox status and post it to my database table when save button clicked.
Store the state in your ListItem, whenever the state of the CheckBox changes:
public class Listitems {
...
public bool isChecked;
...
}
Instead of onClick, listen to the state change instead:
holder.CbHead.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
listitem.isChecked = isChecked
}
});
Finally when binding, make sure to reflect the checked state of the CheckBox:
holder.CbHead.setText(listitem.getHead());
holder.CbHead.setChecked(listitem.isChecked)
You are using a recycler view so while the CheckBox is still on screen it will hold your "checked" state. However once it scrolls off screen, it will be recycled. Hence you need to store the state somewhere, your own ListItem is the best bet

Issues with Searching ListView (Android)

I have been having trouble trying to get my Searchbox working to search the Listview for appropriate rows, and then displaying as required.
Basically, when I type in the searchbox, either the app crashed or gives me 'null object reference' errors from various files (ListView.java, TextView.java etc..)
I suspect it has a lot to do with inexperience on comparing strings between the EditText and the array created from JSON values. Displaying the listview is fine, searching it has been a frustrating hurdle. Would appreciate any help possible, thanks!
My code sections are as below,
ListViewActivity.java
package com.example.myapplication;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.util.Log;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import com.example.myapplication.WaterWellRigsJsonUrl;
import com.example.myapplication.Rig;
public class ListViewActivity extends Activity {
private ListView listview;
private ArrayList<Rig> Rigs;
private ArrayList<Rig> RigsTemp;
private ArrayAdapter<Rig> adapter;
private ArrayAdapter<Rig> adapter2;
private EditText et;
String searchString = "";
private final static String TAG = ListViewActivity.class.getSimpleName();
private final static String url = "http://www.world-rigs.com/waterwellrigs/json.php";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
listview = (ListView) findViewById(R.id.listview);
setListViewAdapter();
getDataFromInternet();
final EditText myFilter = (EditText) findViewById(R.id.myFilter);
myFilter.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
//adapter.getFilter().filter(s);
String searchString = s.toString();
if (s.length() > 0) {
for (int i = 0; i < Rigs.size();i++) {
if (searchString.equalsIgnoreCase(Rigs.get(i).getName())) {
Rig rigtemp = new Rig();
rigtemp.setName(Rigs.get(i).getName());
rigtemp.setImageUrl(Rigs.get(i).getImageUrl());
rigtemp.setRigId(Rigs.get(i).getRigId());
RigsTemp.add(rigtemp);
Log.e("myTag2", "value:" + RigsTemp.size());
}
}
}
adapter2 = new CustomListViewAdapter(ListViewActivity.this, R.layout.item_listview, RigsTemp);
listview.setAdapter(adapter2);
}
});
}
private void getDataFromInternet() {
new WaterWellRigsJsonUrl(this, url).execute();
}
private void setListViewAdapter() {
Rigs = new ArrayList<Rig>();
adapter = new CustomListViewAdapter(this, R.layout.item_listview, Rigs);
listview.setAdapter(adapter);
listview.setTextFilterEnabled(true);
}
//parse response data after asynctask finished
public void parseJsonResponse(String result) {
Log.i(TAG, result);
try {
JSONObject json = new JSONObject(result);
JSONArray jArray = new JSONArray(json.getString("rig_array"));
for (int i = 0; i < jArray.length(); i++) {
JSONObject jObject = jArray.getJSONObject(i);
Rig rig = new Rig();
rig.setName(jObject.getString("name"));
rig.setImageUrl(jObject.getString("image"));
rig.setRigId(jObject.getString("rigid"));
Rigs.add(rig);
Log.e("myTag", Rigs.get(i).getRigId());
}
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
CustomListViewAdapter.java
package com.example.myapplication;
import java.util.List;
import android.app.Activity;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.myapplication.Rig;
import com.loopj.android.image.SmartImageView;
import com.squareup.picasso.Picasso;
public class CustomListViewAdapter extends ArrayAdapter<Rig> {
private Activity activity;
public CustomListViewAdapter(Activity activity, int resource, List<Rig> rigs) {
super(activity, resource, rigs);
this.activity = activity;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
// If holder not exist then locate all view from UI file.
if (convertView == null) {
// inflate UI from XML file
convertView = inflater.inflate(R.layout.item_listview, parent, false);
// get all UI view
holder = new ViewHolder(convertView);
// set tag for holder
convertView.setTag(holder);
} else {
// if holder created, get tag from view
holder = (ViewHolder) convertView.getTag();
}
Rig rig = getItem(position);
holder.name.setText(rig.getName());
holder.authorName.setText("WR" + rig.getRigId());
Picasso.with(activity).load(rig.getImageUrl()).into(holder.image);
return convertView;
}
private static class ViewHolder {
private TextView name;
private TextView authorName;
private ImageView image;
public ViewHolder(View v) {
name = (TextView) v.findViewById(R.id.title);
image = (SmartImageView) v.findViewById(R.id.thumbnail);
// SmartImageView image = (SmartImageView) v.findViewById(R.id.my_image);
authorName = (TextView) v.findViewById(R.id.author);
}
}
}
Also getting the following errors, which do get frustrating but I think it has something to do with null reference in my Adapter or RigsTemp array while searching...
01-30 13:17:45.300 16835-16835/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 16835
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
at android.widget.ListView.setAdapter(ListView.java:487)
at com.example.myapplication.ListViewActivity$1.onTextChanged(ListViewActivity.java:84)
at android.widget.TextView.sendOnTextChanged(TextView.java:7663)
at android.widget.TextView.handleTextChanged(TextView.java:7723)
at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:9440)
at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:964)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:515)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:454)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:33)
at android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.java:685)
at android.view.inputmethod.BaseInputConnection.setComposingText(BaseInputConnection.java:445)
at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:340)
at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:78)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
You don't need to create two adapters and initialize them again and again. Create just one adapter and use notifyDataSetChanged to change data and update ListView
private ArrayList<Rig> RigsTemp;
private ArrayAdapter<Rig> adapter;
Change your function as follows:
private void setListViewAdapter() {
Rigs = new ArrayList<Rig>();
RigsTemp = new ArrayList<Rig>();
adapter = new CustomListViewAdapter(ListViewActivity.this, R.layout.item_listview, RigsTemp);
listview.setAdapter(adapter);
listview.setTextFilterEnabled(true);
}
And Change the TextWatcher code with following code:
public void onTextChanged(CharSequence s, int start, int before, int count) {
String searchString = myFilter.getText().toString();
RigsTemp.clear();
if (s.length() > 0) {
for (int i = 0; i < Rigs.size(); i++) {
if (searchString.equalsIgnoreCase(Rigs.get(i).getName())) {
Rig rigtemp = new Rig();
rigtemp.setName(Rigs.get(i).getName());
rigtemp.setImageUrl(Rigs.get(i).getImageUrl());
rigtemp.setRigId(Rigs.get(i).getRigId());
RigsTemp.add(rigtemp);
}
}
} else {
// Only if you want to show all results when user has not entered anything in EditText
// Else remove this line to show empty ListView at start
RigsTemp.addAll(Rigs);
}
adapter.notifyDataSetChanged();
}

How can I updating only new json data in fragment with swipeRefreshLayout

In this fragment I send a jsonRequest with volley to the server . and I'm setting the swipeRefreshLayout to this fragment , I want to load only new json data but when I use sendJsonRequest() method on the onRefresh() all of the json data is enabled to the recyclerView:
This is my fragment code:
package ghandak.ghandshekan.com.ghandak.fragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import ghandak.ghandshekan.com.ghandak.R;
import ghandak.ghandshekan.com.ghandak.adapters.PostRecyclerAdapter;
import ghandak.ghandshekan.com.ghandak.app.AppController;
import ghandak.ghandshekan.com.ghandak.models.PostData;
/**
* Created by imajid on 12/19/2015.
*/
public class TabFragment3 extends Fragment implements OnRefreshListener{
private RecyclerView allContentRecyclerView;
private String url = "http://kakdo.herokuapp.com/api/news/?format=json";
private List<PostData> postDataList = new ArrayList<PostData>();
private SwipeRefreshLayout swipeRefreshLayout;
//====================================================================================== onCreateView
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab_fragment_3 , container , false);
allContentRecyclerView = (RecyclerView)view.findViewById(R.id.xmlRecyclerViewtabFragment3);
allContentRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
swipeRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.xml_swipe_refresh_layout_tab_fragment_3);
swipeRefreshLayout.setOnRefreshListener(this);
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
//swipeRefreshLayout.setColorSchemeColors();
return view;
}
//====================================================================================== onCreate
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sendJsonRequest();
}
//====================================================================================== sendjsonRequest
private void sendJsonRequest() {
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, url, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
parseJsonResponse(response);
//==========setting adapter to the recyclerview <==
allContentRecyclerView.setAdapter(new PostRecyclerAdapter(getActivity() ,postDataList));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
AppController.getInstance().addToRequestQueue(request);
}
//====================================================================================== parsjsonResponse()
private void parseJsonResponse(JSONArray response) {
if(response == null){
Toast.makeText(getActivity(), "ریسپانس خالی هستش", Toast.LENGTH_SHORT).show();
return;
}else {
Log.d("parsejsonresponse", "response khali nist");
for (int i = 0 ; i < response.length() ; i++ ){
try {
//Toast.makeText(getActivity(), "ریسپانس میگیرم ", Toast.LENGTH_SHORT).show();
JSONObject currentPost = response.getJSONObject(i);
//Log.d("currentPost", "currentPost ro gereftam");
PostData postData = new PostData();
postData.setTitle(currentPost.getString("title"));
//Toast.makeText(getActivity() , currentPost.getString("title") , Toast.LENGTH_SHORT).show();
postData.setCreate(currentPost.getString("create"));
postDataList.add(postData);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
#Override
public void onRefresh() {
sendJsonRequest();
swipeRefreshLayout.setRefreshing(false);
}
}
Now my question is in the OnRefresh method , what can I write to load only new json data, not all of the exists json.
Add this line in your code
postDataList.clear(); in your code given in bellow.
Updated:
#Override
public void onResponse(JSONArray response) {
if(response == null )
return;
postDataList.clear();
parseJsonResponse(response);
//==========setting adapter to the recyclerview <==
allContentRecyclerView.setAdapter(new PostRecyclerAdapter(getActivity() ,postDataList));
}
Note: when ever you create any kind of list max create adapter instance once in your code, After change list data you just need to call 'adapterInstance.notifyDataSetChange();'
This is the best practice instead of creating list every time it's better to refresh list items, Further info check here
add this code ,
private SwipeRefreshLayout mSwipeRefreshLayout;
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
}, SPLASH_DISPLAY_LENGTH);
}
});
when you want to refresh it call,
mSwipeRefreshLayout.setRefreshing(true);
swipeContainer = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
swipeContainer.setOnRefreshListener(new OnRefreshListener()
{
#Override
public void onRefresh()
{
//clear your old data
callForData();
//swipeContainer.setRefreshing(false); use this while get data and set in you ui
}
});
// Configure the refreshing colors
swipeContainer.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light, android.R.color.holo_orange_light, android.R.color.holo_red_light);

Categories