Issues with Searching ListView (Android) - java

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

Related

BaseAdapter crashes on notifyDataSetChanged update?

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!

Custom Dialog not working within a Adapter, Crashes App

I have a listview with a requestQueue that calls POST to mysqli database to get a array JSONobject. A base Adapter is use for the listview to layout the data. There a button on every item on the list. I try to figure out why the custom dialog is crashing the app. It might be how I call the dialog. I know showing the dialog is the cause for the crash.
Sensors_Activity.java
public class Sensors_Activity extends AppCompatActivity
{
#Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensors_);
final ListView S_lv = (ListView) findViewById(R.id.S_ListView);
RequestQueue requestQueue;
requestQueue = (RequestQueue) Volley.newRequestQueue(getApplicationContext());
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(POST, DBStrings.DataUrl, null, new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response)
{
....
SensorsAdapter sensorsAdapter = new SensorsAdapter(getApplicationContext(),id,room_id,state,type,value);
S_lv.setAdapter(sensorsAdapter);
....
});//Response ends here
requestQueue.add(jsonObjectRequest);
}//OnCreate ends here
}
SensorAdapter
package com.example.djwiz.test5;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.security.AccessController;
import java.util.zip.Inflater;
import static java.security.AccessController.getContext;
public class SensorsAdapter extends BaseAdapter
{
LayoutInflater mInflater;
String[] Id_Array;
String[] Room_Id_Array;
String[] State_Array;
String[] Type_Array;
String[] Value_Array;
Context TheContext;
public SensorsAdapter(Context c, String[] I, String[] R, String[] S, String[] T, String[] V)
{
Id_Array = I;
Room_Id_Array = R;
State_Array = S;
Type_Array = T;
Value_Array = V;
TheContext = c;
mInflater = (LayoutInflater.from(c));
}
#Override
public int getCount()
{
return Id_Array.length;
}
#Override
public Object getItem(int position)
{
return Id_Array[position];
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public View getView(final int positon, View convertView, ViewGroup parent)
{
View v = mInflater.inflate(R.layout.sensor_list, null);
TextView idtv = (TextView) v.findViewById(R.id.S_id_TV);
TextView roomtv = (TextView) v.findViewById(R.id.S_room_id_TV);
final TextView typetv = (TextView) v.findViewById(R.id.S_type_TV);
TextView valuetv = (TextView) v.findViewById(R.id.S_value_TV);
TextView statetv = (TextView) v.findViewById(R.id.S_state_TV);
final Button Setting_btn = (Button) v.findViewById(R.id.S_Settings_Btn);
Setting_btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(TheContext, typetv.getText() +" was click at " + (positon +1) , Toast.LENGTH_SHORT).show();
String type;
type = typetv.getText().toString();
if(type.equals("lock"))
{
AlertDialog.Builder S_LockBuilder;
LayoutInflater inflater = (LayoutInflater) TheContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
S_LockBuilder = new AlertDialog.Builder(TheContext);
final View S_LockView;
S_LockView = inflater.inflate(R.layout.linear_lock_dialog,null);
TextView L_State_TV;
TextView L_Value_TV;
ToggleButton L_T_BTN;
L_T_BTN = (ToggleButton) S_LockView.findViewById(R.id.D_TOGGLE_BTN);
S_LockBuilder.setView(S_LockView);
AlertDialog Lockdialog = S_LockBuilder.create();
Lockdialog.show();
}
}
});
String ID = Id_Array[positon];
String ROOM = Room_Id_Array[positon];
String STATE = State_Array[positon];
String TYPE = Type_Array[positon];
String VALUE = Value_Array[positon];
idtv.setText(ID);
roomtv.setText(ROOM);
typetv.setText(TYPE);
valuetv.setText(VALUE);
statetv.setText(STATE);
return v;
}
}
Logcat
02-20 00:43:22.126 13775-13775/com.example.djwiz.test5 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.djwiz.test5, PID: 13775
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:765)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:330)
at com.example.djwiz.test5.SensorsAdapter$1.onClick(SensorsAdapter.java:106)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Any help would be graceful.
Thank You
First you have to change
SensorsAdapter sensorsAdapter = new
SensorsAdapter(Sensors_Activity.this,id,room_id,state,type,value);
S_lv.setAdapter(sensorsAdapter);
please pass activity not context.
Then in your adapter change
Context TheContext;
to
Activity theActivity
Then pass your theActivity to dialog
S_LockBuilder = new AlertDialog.Builder(theActivity);
You need an Activity Context for Dialogs. An Application Context does not work.
Write like this:
SensorsAdapter sensorsAdapter = new SensorsAdapter(Sensors_Activity.this,id,room_id,state,type,value);
S_lv.setAdapter(sensorsAdapter);

Adapter not working inside asyncTask when notifyDataSetChanged?

i've got problem when trying to implement loadmore, exactly problem is adapter.notifyDataSetChanged inside AsyncTask. i trying to implement from this tuts https://github.com/shontauro/android-pulltorefresh-and-loadmore
, this tuts try implementing using extend ListActivity in Class, but i'm using extend Fragment, anyway this code is working, but just data not updated when trying to get data from loadmore. i'm sorry if my language is bad :)
this is my class :
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.bye.swipetab.adapter.ViewPagerAdapter;
import com.viewpagerindicator.CirclePageIndicator;
import com.viewpagerindicator.UnderlinePageIndicator;
import java.util.Arrays;
import java.util.LinkedList;
public class Tour extends Fragment {
private static final String TAG = Tour.class.getSimpleName();
View myView;
private String[] values ;
private static final String brand_value = "brand_value";
// Array of strings...
String[] mobileArray = {"Android","IPhone","WindowsMobile","Blackberry","WebOS"};
// list with the data to show in the listview
private LinkedList<String> mListItems;
// The data to be displayed in the ListView
private String[] mNames = { "Fabian", "Carlos", "Alex", "Andrea", "Karla",
"Freddy", "Lazaro", "Hector", "Carolina", "Edwin", "Jhon",
"Edelmira", "Andres" };
// Declare Variables
ViewPager viewPager;
PagerAdapter vAdapter;
String[] rank;
String[] country;
String[] population;
int[] flag;
UnderlinePageIndicator mIndicator;
ListView listView;
ArrayAdapter adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = inflater.inflate(R.layout.tour_layout, null);
View header = inflater.inflate(R.layout.tour_header_layout, null);
//View footer = inflater.inflate(R.layout.tour_footer_layout, null);
listView = (ListView) myView.findViewById(android.R.id.list);
listView.addHeaderView(header, null, false); // header will not be clickable
mListItems = new LinkedList<String>();
mListItems.addAll(Arrays.asList(mNames));
adapter = new ArrayAdapter<String>(getActivity(), R.layout.tour_listview, R.id.MobileArray, mNames);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// When clicked, show a toast with the TextView text
String brand_text = ((TextView) view.findViewById(R.id.MobileArray)).getText().toString();
//Toast.makeText(getApplicationContext(),brand_text, Toast.LENGTH_SHORT).show();
// Starting single contact activity
Intent in = new Intent(getActivity(), TourActivity.class);
in.putExtra(brand_value, brand_text);
in.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(in);
}
});
population = new String[] {
"1,354,040,000",
"1,210,193,422",
"315,761,000",
"315,123,000",
"363,752,000" };
flag = new int[] {
R.drawable.offline_ide_4,
R.drawable.offline_ide_1,
R.drawable.offline_ide_2,
R.drawable.offline_ide_3,
R.drawable.offline_ide_5 };
// Locate the ViewPager in viewpager_main.xml
viewPager = (ViewPager) myView.findViewById(R.id.pager);
// Pass results to ViewPagerAdapter Class
vAdapter = new ViewPagerAdapter(getContext(), rank, country, population, flag);
// Binds the Adapter to the ViewPager
viewPager.setAdapter(vAdapter);
CirclePageIndicator indicator = (CirclePageIndicator)myView.findViewById(R.id.indicator);
indicator.setViewPager(viewPager);
final float density = getResources().getDisplayMetrics().density;
indicator.setRadius(5 * density);
//indicator.setBackgroundColor(0x7f0c006a);
//indicator.setPageColor(R.color.black);
//indicator.setFillColor(R.color.tab_bg_yellow_deep);
//indicator.setStrokeColor(R.color.tab_bg_yellow_deep);
//indicator.setStrokeWidth(2 * density);
// set a listener to be invoked when the list reaches the end
((LoadMoreListView) listView)
.setOnLoadMoreListener(new LoadMoreListView.OnLoadMoreListener() {
public void onLoadMore() {
// Do the work to load more items at the end of list
// here
new LoadDataTask().execute();
}
});
return myView;
}
private class LoadDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
if (isCancelled()) {
return null;
}
// Simulates a background task
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
for (int i = 0; i < mobileArray.length; i++) {
mListItems.add(mobileArray[i]);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mListItems.add("Added after load more");
// We need notify the adapter that the data have been changed
adapter.notifyDataSetChanged();
// Call onLoadMoreComplete when the LoadMore task, has finished
((LoadMoreListView) listView).onLoadMoreComplete();
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
// Notify the loading more operation has finished
((LoadMoreListView) listView).onLoadMoreComplete();
}
}
}
please tell me why this is not working ?
mListItems is not used for anything.
mNames is the one linked to the adapter, not mListItems which you are filling in the AsyncTask, may be you should review that.
mListItems.addAll(Arrays.asList(mNames));
adapter = new ArrayAdapter<String>(getActivity(), R.layout.tour_listview, R.id.MobileArray, mNames);
and then you do
for (int i = 0; i < mobileArray.length; i++) {
mListItems.add(mobileArray[i]);
}

Display image in GridView using Picasso

I want to build an app that displays images in a gridview by using the picasso library. This is my code. The image didn't load. In Picasso log, after request it always error to load. Can you help me ?Please Thank you
UPDATE
CustomGridViewAdapter.Java
import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
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.squareup.picasso.Picasso;
import java.util.ArrayList;
/**
* Created by Nicky-PC on 4/9/2016.
*/
public class CustomGridViewAdapter extends ArrayAdapter<gridItem> {
Context context;
int layoutResourceId;
ArrayList<gridItem> data = new ArrayList<gridItem>();
public CustomGridViewAdapter(Context context, int layoutResourceId,
ArrayList<gridItem> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
public void setGridData(ArrayList<gridItem> mGridData)
{
this.data=mGridData;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
RecordHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new RecordHolder();
holder.txtTitle = (TextView) row.findViewById(R.id.tvItem);
holder.imageItem = (ImageView) row.findViewById(R.id.imageView);
row.setTag(holder);
} else {
holder = (RecordHolder) row.getTag();
}
gridItem item = data.get(position);
holder.txtTitle.setText(item.getBarang());
Picasso.with(context).
load(item.getImageUrl()).
into(holder.imageItem);
return row;
}
static class RecordHolder {
TextView txtTitle;
ImageView imageItem;
}
}
MainActivity.Java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.media.Image;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends ActionBarActivity {
JSONParser jParser= new JSONParser();
ArrayList<HashMap<String, String>> nameList;
JSONArray names=null;
GridView data;
private static final String URL_TEST_BARANG= "http://lomapod.azurewebsites.net/readBarang.php";
private static final String TAG_PESAN = "message";
private static final String TAG_HASIL = "result";
private static final String TAG_BARANG = "nama_barang";
private static final String TAG_IMAGE= "image_name";
ImageView imageview;
CustomGridViewAdapter mGridAdapter;
ArrayList<gridItem> mGridData;
public MainActivity()
{}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
data=(GridView) findViewById(R.id.lvSeller);
nameList= new ArrayList<HashMap<String, String>>();
imageview =(ImageView) findViewById(R.id.imageView);
mGridData=new ArrayList<>();
mGridAdapter=new CustomGridViewAdapter(this,R.layout.grid_item,mGridData);
new AmbilDataJson("1").execute();
}
public class AmbilDataJson extends AsyncTask<String,String,String> {
String id;
int sukses=0;
public AmbilDataJson(String id) {
this.id=id;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id_penjual",id));
try
{
JSONObject json = jParser.makeHttpRequest(URL_TEST_BARANG, "GET", params);
gridItem item=null;
if(json != null)
{
sukses = json.getInt(TAG_PESAN);
if(sukses == 0)
{
nameList = new ArrayList<HashMap<String,String>>();
Log.d("Semua Nama: ", json.toString());
names = json.getJSONArray(TAG_HASIL);
for(int i = 0; i < names.length();i++)
{
JSONObject c = names.getJSONObject(i);
String barang = c.getString(TAG_BARANG);
String image = "lomapod.esy.es/assets/"+c.getString(TAG_IMAGE);
item = new gridItem();
item.setBarang(barang);
item.setImageUrl(image);
HashMap<String,String> map = new HashMap<String,String>();
map.put(TAG_BARANG,barang);
map.put(TAG_IMAGE,image);
nameList.add(map);
mGridData.add(item);
}
}
}
}catch(JSONException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
if(sukses == 0)
{
CustomGridViewAdapter adapter = new CustomGridViewAdapter(
MainActivity.this,R.layout.grid_item,mGridData);
if(mGridData.size()>0)
{
mGridAdapter.setGridData(mGridData);
data.setAdapter(adapter);
}
else
Toast.makeText(getApplicationContext(),"Error - No Data Available", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(MainActivity.this,"Failed",Toast.LENGTH_LONG);
}
}
}
}
CustomGridViewAdapter adapter = new CustomGridViewAdapter(
MainActivity.this,R.layout.grid_item,mGridData);
mGridAdapter.setGridData(mGridData);
data.setAdapter(adapter);
mGridData is empty, you have not added data for this list. And you don't not need initialize new adapter.
You didn't add values to mGridData thats why its not showing anything. Before passing values to adapter check the size of mGridData.
`#Override
protected void onPostExecute(String s) {
if(sukses == 0)
{
CustomGridViewAdapter adapter = new CustomGridViewAdapter(
MainActivity.this,R.layout.grid_item,mGridData);
if(mGridData.size()>0)
{
mGridAdapter.setGridData(mGridData);
data.setAdapter(adapter);
}
else
Toast.makeText(getApplicationContext(),"Error - No Data Available", Toast.LENGTH_SHORT).show();
}`
The reason why your GridView is not showing anything is because the ArrayList<gridItem> you are passing to your CustomGridViewAdapter is empty.
You have initialized your ArrayList<gridItem> in MainActivity but never added a any item to the list.
There are some things you need to change in your program to make it work.
Since you are added server response in the ArrayList<HashMap<String, String>> nameList, you need to pass that ArrayList to your Adapter, and then use that ArrayList's items to bind in your grid's textView and imageView.
In onPostExecute(), initialize your adapter as,
CustomGridViewAdapter adapter = new CustomGridViewAdapter(MainActivity.this,R.layout.grid_item, nameList);
data.setAdapter(adapter);
//you don't even need to call mGridAdapter.setGridData(mGridData) method.
Also change your Adapter's constructor as,
public CustomGridViewAdapter(Context context, int layoutResourceId,
ArrayList<HashMap<String, String>> nameList) {
....
}

NullPointerException when downloading images for ImageView in android

I am attempting to brush up on my android for a project at work, and it seams that im more out of touch than i first thought.
I am creating an app that uploads pictures to a remote server and then shows these uploads as thumbnails.
The section i am struggling is with downloading the image and applying it to the image view within a list view.
Im receiving a Null Pointer Exception which is never nice.
Im not sure if this is due to me starting a number of ASync tasks (one for each image) or if its something more obvious
Stack Trace
Process: com.example.alex.documentupload, PID: 5788
java.lang.NullPointerException
at com.example.alex.documentupload.DownloadImageTask.onPostExecute(DownloadImage.java:35)
at com.example.alex.documentupload.DownloadImageTask.onPostExecute(DownloadImage.java:14)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5748)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
Android Code
Show images Class
package com.example.alex.documentupload;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import com.example.alex.documentupload.JSONParser;
import com.example.alex.documentupload.DownloadImageTask;
public class ShowImages extends Activity {
ListView list;
TextView ver;
TextView name;
TextView api;
ImageView img;
Button Btngetdata;
ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();
//URL to get JSON Array
private static String url = "http://www.500kgiveaway.co.uk/getimagesmob.php";
//JSON Node Names
private static final String TAG_PATH = "path";
JSONArray android = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_images);
oslist = new ArrayList<HashMap<String, String>>();
new JSONParse().execute();
Btngetdata = (Button)findViewById(R.id.getdata);
Btngetdata.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// clear the list before adding more
//update the list
new JSONParse().execute();
}
});
}
private class JSONParse extends AsyncTask<String, String, JSONArray> {
private ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
ver = (TextView)findViewById(R.id.vers);
name = (TextView)findViewById(R.id.name);
api = (TextView)findViewById(R.id.api);
img = (ImageView)findViewById(R.id.img);
pDialog = new ProgressDialog(ShowImages.this);
pDialog.setMessage("Getting Data ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected JSONArray doInBackground(String... args) {
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONArray json = jParser.getJSONFromUrl(url);
return json;
}
#Override
protected void onPostExecute(JSONArray json) {
pDialog.dismiss();
try {
// Getting JSON Array from URL
android = json;
for(int i = 0 ; i < android.length(); i++){
JSONObject c = android.getJSONObject(i);
// Storing JSON item in a Variable
String path = c.getString(TAG_PATH);
// Adding value HashMap key => value
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_PATH, path);
oslist.add(map);
list=(ListView)findViewById(R.id.list);
ListAdapter adapter = new SimpleAdapter(ShowImages.this, oslist,
R.layout.list_v,
new String[] { TAG_PATH }, new int[] {
R.id.vers});
list.setAdapter(adapter);
new DownloadImageTask((ImageView) list.findViewById(R.id.img))
.execute("http://www.500kgiveaway.co.uk/" + path);
// list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//
// #Override
// public void onItemClick(AdapterView<?> parent, View view,
// int position, long id) {
// Toast.makeText(ShowImages.this, "You Clicked at "+oslist.get(+position).get("name"), Toast.LENGTH_SHORT).show();
// }
// });
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void loadcamera(View view) {
// Do something in response to button
Intent myIntent = new Intent(ShowImages.this, MainActivity.class);
myIntent.putExtra("dir", "BS"); //Optional parameters
ShowImages.this.startActivity(myIntent);
}
}
DownloadImages Class
package com.example.alex.documentupload;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.io.InputStream;
/**
* Created by Alex on 03/05/2015.
*/
class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
This turned out to be a bit of a tricky fix, but got there in the end.
The issue was that i was unable to reference the imageview object inside the listview object whilst using a SimpleAdaptor.
The answer is that you need to create a custom class that extends SimpleAdaptor
I ended up using the picasso library, not because it helped fix the problem, more that it offered some image processing features, like resize etc which i had not previously allowed for.
I followed this answer Android - How can diplay pictures in a simpleApapter list view
However i run in to additional issues with context.
Here is my custom class that extends SimpleAdaptor
package com.example.alex.documentupload;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import com.squareup.picasso.Picasso;
import java.util.List;
import java.util.Map;
public class ExtendedAdaptor extends SimpleAdapter {
public static Context NewContext;
public ExtendedAdaptor(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to){
super(context, data, resource, from, to);
NewContext = context;
}
public View getView(int position, View convertView, ViewGroup parent){
// here you let SimpleAdapter built the view normally.
View v = super.getView(position, convertView, parent);
// Then we get reference for Picasso
ImageView img = (ImageView) v.getTag();
if(img == null){
img = (ImageView) v.findViewById(R.id.img);
v.setTag(img); // <<< THIS LINE !!!!
}
// get the url from the data you passed to the `Map`
String url = ((Map)getItem(position)).get("path").toString();
// do Picasso
// maybe you could do that by using many ways to start
Picasso.with(NewContext).load(url)
.resize(100, 100).into(img);
// return the view
return v;
}
}
and here is how i called it
ListView list = (ListView) findViewById(R.id.list);
ListAdapter adapter =
new ExtendedAdaptor(
context,
oslist,
R.layout.list_v,
new String[]{TAG_PATH},
new int[]{R.id.vers});
list.setAdapter(adapter);
Its all works pretty well, the image cache and image only download if they change.
I hope this helps someone else in the future
Thanks to all that contributed

Categories