Android BaseAdapter Dealing with an Empty ArrayList - java

I'm trying to populate a ListView with an ArrayList> using a base adapter. The ArrayList is populated by a database, and it is possible for the database to have no entries, and thus a empty ArrayList, for example when the app is launched for the first time. While the ArrayList is empty, I receive a non de-script "java.lang.RuntimeException: Unable to start activity ComponentInfo ... java.lang.NullPointerException".
My onCreate method looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.samples_list_layout);
mContext = getApplicationContext();
lv = getListView();
list = myDatabase.getInstance(mContext).getAllSamples();
sa = new SamplesAdapter(this, list);
lv.setAdapter(sa);
registerForContextMenu(lv);
}
Setting lv.setAdapter(null) will get the app to display the empty list view I have set up. However, when I leave it up to the BaseAdapter, I get the error.
I've followed the 2 Android List8.java and List14.java examples, and either way give the same results.
My BaseAdapter class looks like this:
public class SamplesAdapter extends BaseAdapter {
private static final String SAMPLE_NAME_COL = "name";
private static final String SAMPLE_HOST_COL = "host";
private static final String SAMPLE_ICON_COL = "icon";
private static final String SAMPLE_MODIFIED_STAMP_COL = "moddate";
private Context mContext;
private ArrayList<HashMap<String, String>> samples = new ArrayList<HashMap<String, String>>();
public SamplesAdapter(Context c, ArrayList<HashMap<String, String>> list){
mContext = c;
samples = list;
}
public int getCount() {
return samples.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.samples_row_layout, parent, false);
TextView name = (TextView) v.findViewById(R.id.samples_name);
name.setText(samples.get(position).get(SAMPLE_NAME_COL));
TextView host = (TextView) v.findViewById(R.id.samples_host);
host.setText(samples.get(position).get(SAMPLE_HOST_COL));
TextView moddate = (TextView) v.findViewById(R.id.samples_mod_stamp);
moddate.setText(samples.get(position).get(SAMPLE_MODIFIED_STAMP_COL));
return v;
}
}
I should also note that the ListView properly displays items when there is something to show. It only fails when the ArrayList is empty. Also, I'm using Android 2.2 (Not the greatest, I know). Any help would be greatly appreciated.

let getCount return 0, in orded to avoid the NPE:
public int getCount() {
return (samples == null) ? 0 : samples.size();
}

Related

Displaying image retrieved from server

I am working on an Android app, in which the user uploads a photo. Now, I am calling a method from the server, which will return me a list of users. I would like to display this list along with the photos.
The images stored in the server are in byte-array. So I am converting them to String and then to Bitmap for showing. Unfortunately, it is not working as I am doing stuff with a Adapters as well. The image retrieved in adapter class is null. What am I doing wrong?
OtherUsers.java :
public class OtherUsers extends Activity {
private PersonServiceImpl personService = new PersonServiceImpl();
private static volatile List<RestPerson> restPersonList = new ArrayList<>();
public static final String firstName = "firstname";
public static final String userImage = "userimage";
static final Long userId = (long)0;
ListView listView;
UserAdapter userAdapter;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.displayuserlist);
restPersonList = this.personService.getOtherUsers();
// Base64 base64Encoder = new Base64();
ArrayList<HashMap<String, String>> usersArrayHashList = new ArrayList<>();
for(RestPerson restPerson : restPersonList){
HashMap<String, String> restDisplay = new HashMap<>();
restDisplay.put("userId",String.valueOf(restPerson.getUserId()));
restDisplay.put("firstName",restPerson.getFirstName());
restDisplay.put("userImage","data:image/png;base64," + Base64.encode(restPerson.getProfilePhoto()));
usersArrayHashList.add(restDisplay);
}
listView = (ListView) findViewById(R.id.usersdisplaylist);
userAdapter = new UserAdapter(this,usersArrayHashList);
listView.setAdapter(userAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Long userid = restPersonList.get(position).getUserId();
Log.d("Userid is ", String.valueOf(userid));
}
});
UserAdapter class :
public class UserAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater = null;
public UserAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null)
view = inflater.inflate(R.layout.userprofiles, null);
TextView username = (TextView) view.findViewById(R.id.userName);
ImageView userImage = (ImageView) view.findViewById(R.id.userImage);
HashMap<String, String> usersList = new HashMap<>();
usersList = data.get(position);
username.setText(usersList.get(OtherUsers.firstName));
String image = usersList.get(OtherUsers.userImage);
Log.d("Image is ",image);
byte[] newImageBytes = image.getBytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(newImageBytes,0,newImageBytes.length);
userImage.setImageBitmap(bitmap);
userImage.setImageBitmap(null);
return view;
}
}
If there is any other information required, kindly let me know. Thanks.
Update
Sorry, forgot to put LogCat
08-24 13:43:16.618 29948-29948/internetlegion.com.gradlecheck E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: internetlegion.com.gradlecheck, PID: 29948
java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:139)
at internetlegion.com.gradlecheck.Adapters.UserAdapter.getView(UserAdapter.java:62)
at android.widget.AbsListView.obtainView(AbsListView.java:2347)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1270)
at android.widget.ListView.onMeasure(ListView.java:1182)
at android.view.View.measure(View.java:17547)
data struct that you have used in adapter is very strange. it's better to create one class with three property and send one list of those to adapter class.
any way, your problem is :
public static final String userImage = "userimage";
you define userImage with value userimage, then you insert into hashmap with "userImage" that is not equal with value of userImage ( value have lower case i) then you have try to get "userimage" from hashmap that is not exists, so value is null.
Answer:
you can change following line:
restDisplay.put("userImage","data:image/png;base64," + Base64.encode(restPerson.getProfilePhoto()));
to
restDisplay.put(userImage,"data:image/png;base64," + Base64.encode(restPerson.getProfilePhoto()));
but better way is create custom object.

Undefined Constructor in android

I'm making an app that deals with a fragment and I keep getting an undefined error for a constructor.
`
public class ClientFragment extends Fragment {
private static final ClientFragment This = null;
final ClientFragment context = This;
private static String TAG = "This thing here";
private static final String DIALOG_IMAGE = "image";
private static final int REQUEST_PHOTO = 1;
static final String EXTRA_MEM_ID = "com.example.project2.memID";
private Scrap mScraps;
Uri imageFileUri;
public static ClientFragment newInstance(UUID memID) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_MEM_ID, memID);
ClientFragment fragment = new ClientFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//this snags the UUID sent from MainActivity and tosses it to BookMarks
UUID memId = (UUID)getArguments().getSerializable(EXTRA_MEM_ID);
mScraps = BookMarks.get(getActivity()).getScraps(memId);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_scraps, parent, false);
final ListView mListView= (ListView)v.findViewById(R.id.listview);
ScrapAdapter adapter = new ScrapAdapter(mScraps);
mListView.setAdapter(adapter); //setListAdapter sets the adapter to a specific listview
return v;
}
private static final int TAKE_PICTURE_REQUEST = 0;
private class ScrapAdapter extends ArrayAdapter<Scrap> {
public ScrapAdapter(ArrayList<Scrap> scraps) {
super(getActivity(), 0, scraps);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If we weren't given a view, inflate one
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_memory, null);
}
// Configure the view
Scrap c = getItem(position);
//shows title
TextView titleTextView =(TextView)convertView.findViewById(R.id.list_item_titleTextView);
titleTextView.setText(c.getTitle());
//shows date memory was made
TextView dateTextView =(TextView)convertView.findViewById(R.id.list_item_dateTextView);
dateTextView.setText(c.getDate().toString());
return convertView;
}
}}`
The error is coming from ScrapAdapter adapter = new ScrapAdapter(mScraps); specifically the new ScrapAdapter(mScraps);
The error I receive is "The constructor ClientFragment.ScrapAdapter(Scrap) is undefined"
your constructor accepts an ArrayList<Scrap> as argument
public ScrapAdapter(ArrayList<Scrap> scraps)
but you are passing an Scrap object to it instead
ScrapAdapter adapter = new ScrapAdapter(mScraps);
Either pass ArrayList of Scrap to ScrapAdapter :
ArrayList<Scrap> mScraps;
ScrapAdapter adapter = new ScrapAdapter(mScraps);
Or change ScrapAdapter constructor parameter ArrayList to Scrap :
public ScrapAdapter(Scrap scraps) {
super(getActivity(), 0, scraps);
}
Your constructor need an ArrayList :
public ScrapAdapter(ArrayList<Scrap> scraps)
But you are passing an Object, not the ArrayList of Object :
private Scrap mScraps;
ScrapAdapter adapter = new ScrapAdapter(mScraps);
Maybe what you need to do is creating an ArrayList of Scrap and pass it. Or maybe, you want to change your constructor's parameter to receive a Scrap instead of ArrayList.

android UnsupportedOperationException in ArrayAdapter<String>

I am trying to create an onDisimiss listener to my app as for now this is what i have
The activity
public class listview_test extends Activity {
ListView list;
String[] web = {
"Google Plus",
"Twitter",
"Windows",
} ;
Integer[] imageId = {
R.drawable.ic_launcher,
R.drawable.icon,
R.drawable.ic_launcher,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_test);
final CustomList adapter = new
CustomList(listview_test.this, web, imageId);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(listview_test.this, "You Clicked at " +web[+ position], Toast.LENGTH_SHORT).show();
}
});
SwipeDismissListViewTouchListener touchListener =
new SwipeDismissListViewTouchListener(
list,
new SwipeDismissListViewTouchListener.DismissCallbacks() {
#Override
public boolean canDismiss(int position) {
return true;
}
#Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
adapter.remove(adapter.getItem(position));
}
adapter.notifyDataSetChanged();
}
}
);
list.setOnTouchListener(touchListener);
// Setting this scroll listener is required to ensure that during ListView scrolling,
// we don't look for swipes.
list.setOnScrollListener(touchListener.makeScrollListener());
}
}
And the custom adapter
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] web;
private final Integer[] imageId;
public CustomList(Activity context,
String[] web, Integer[] imageId) {
super(context, R.layout.weather_item, web);
this.context = context;
this.web = web;
this.imageId = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.weather_item, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.city);
ImageView imageView = (ImageView) rowView.findViewById(R.id.info_image);
txtTitle.setText(web[position]);
imageView.setImageResource(imageId[position]);
return rowView;
}
For some reason every time i am swiping an item to dismiss it force closes and gives me this exception
java.lang.UnsupportedOperationException
In this line
adapter.remove(adapter.getItem(position));
java.lang.UnsupportedOperationException
is thrown when you back an Adapter by an array or non-modifiable List. Since you cannot change their size, deleting is impossible.
Instead, modify your Adapter so it accepts a List instead of an array and make sure that the List you pass off is fully flexible.
Something like
List <String> web = new ArrayList <String> ();
web.add ("Google Plus");
web.add ("Twitter");
//etc.
is enough to ensure a flexible list.
This means that your CustomList adapter should also call up to the superclass constructor that also accepts in a List, which in this case is
public ArrayAdapter (Context context, int resource, List<T> objects)
For more information refer to the ArrayAdapter documentation.

Lazy Adapter for the Call Logs

I have created an application that can show call logs. I am using LazyAdapter class. I am showing an icon according to the call type: Missed / Incoming / Outgoing. This part is not working properly. The display of text like name, number, date and time is showing just fine except the Call type?
Here is what I am trying to do:
public class LazyAdapter extends BaseAdapter
{
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d)
{
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount()
{
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.callist, null);
TextView name = (TextView)vi.findViewById(R.id.name);
TextView number = (TextView)vi.findViewById(R.id.phone_number);
TextView date = (TextView)vi.findViewById(R.id.date);
TextView time = (TextView)vi.findViewById(R.id.time);
TextView duration = (TextView)vi.findViewById(R.id.duration);
ImageView callType = (ImageView)vi.findViewById(R.id.calType);
ImageView clock = (ImageView)vi.findViewById(R.id.Clock);
HashMap<String, String> pro = new HashMap<String, String>();
pro = data.get(position);
if((pro.get(ListOfCall.contactName)!=null))
{
name.setText(pro.get(ListOfCall.contactName));
}
else
{
name.setText("Unknown");
}
number.setText(pro.get(ListOfCall.phone));
date.setText(pro.get(ListOfCall.DateOfCall));
time.setText(pro.get(ListOfCall.TimeOfCall));
String type = pro.get(ListOfCall.typeofCall);
if(type.equalsIgnoreCase("OUTGOING"))
{
callType.setImageResource(R.drawable.outgoing);
duration.setText(pro.get(ListOfCall.durationOfCall));
}
else if(type.equalsIgnoreCase("INCOMING"))
{
callType.setImageResource(R.drawable.incoming);
duration.setText(pro.get(ListOfCall.durationOfCall));
}
else if(type.equalsIgnoreCase("MISSED"))
{
callType.setImageResource(R.drawable.missed);
duration.setVisibility(4);
clock.setVisibility(4);
}
return vi;
}
}
I am not really sure where the problem is coming because I am able get correct results in the arraylist called data in the top. Things change when I move the arraylist to Hashmap called pro.
Again the values are coming up properly except the call type and it's corresponding images are not coming up.
Can somebody help me out to fix this up?
Figured out the conditions that were in LazyAdapter class didn't work as required. Removed the condition and added them in before class that was sending values to LazyAdapter class.
Works fine now!!
Thanks!

Dynamic ListView in Android app

Is there a working example out there that demonstrates how to append additional rows in ListView dynamically?
For example:
you are pulling RSS feeds from
different domains
you then display the first 10 items
in the ListView (while you have
other threads running in the
background continue pulling feeds)
you scroll and reach the bottom of
the List and click at a button to
view more items
the ListView will then get appended
with additional 10 items, which
makes 20 items now in total.
Any advice how to accomplish this?
Nicholas
To add new item to your list dynamically you have to get adapter class from your ListActivity and simply add new elements. When you add items directly to adapter, notifyDataSetChanged is called automatically for you - and the view updates itself. You can also provide your own adapter (extending ArrayAdapter) and override the constructor taking List parameter. You can use this list just as you use adapter, but in this case you have to call adapter.notifyDataSetChanged() by yourself - to refresh the view.
Please, take a look at the example below:
public class CustomList extends ListActivity {
private LayoutInflater mInflater;
private Vector<RowData> data;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
data = new Vector<RowData>();
RowData rd = new RowData("item1", "description1");
data.add(rd);
rd = new RowData("item2", "description2");
data.add(rd);
rd = new RowData("item2", "description3");
data.add(rd);
CustomAdapter adapter = new CustomAdapter(this, R.layout.custom_row,R.id.item, data);
setListAdapter(adapter);
getListView().setTextFilterEnabled(true);
}
public void onListItemClick(ListView parent, View v, int position, long id) {
CustomAdapter adapter = (CustomAdapter) parent.getAdapter();
RowData row = adapter.getItem(position);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(row.mItem);
builder.setMessage(row.mDescription + " -> " + position );
builder.setPositiveButton("ok", null);
builder.show();
}
/**
* Data type used for custom adapter. Single item of the adapter.
*/
private class RowData {
protected String mItem;
protected String mDescription;
RowData(String item, String description){
mItem = item;
mDescription = description;
}
#Override
public String toString() {
return mItem + " " + mDescription;
}
}
private class CustomAdapter extends ArrayAdapter<RowData> {
public CustomAdapter(Context context, int resource,
int textViewResourceId, List<RowData> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
//widgets displayed by each item in your list
TextView item = null;
TextView description = null;
//data from your adapter
RowData rowData= getItem(position);
//we want to reuse already constructed row views...
if(null == convertView){
convertView = mInflater.inflate(R.layout.custom_row, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
//
holder = (ViewHolder) convertView.getTag();
item = holder.getItem();
item.setText(rowData.mItem);
description = holder.getDescription();
description.setText(rowData.mDescription);
return convertView;
}
}
/**
* Wrapper for row data.
*
*/
private class ViewHolder {
private View mRow;
private TextView description = null;
private TextView item = null;
public ViewHolder(View row) {
mRow = row;
}
public TextView getDescription() {
if(null == description){
description = (TextView) mRow.findViewById(R.id.description);
}
return description;
}
public TextView getItem() {
if(null == item){
item = (TextView) mRow.findViewById(R.id.item);
}
return item;
}
}
}
You can extend the example above and add "more" button - which just add new items to your adapter (or vector). Regards!

Categories

Resources