I am using ListView
with a custom ArrayAdapter
, and everything is working fine when I run my app in AVD
emulator, but when I install it on my phone my app crashes when I touch any ListView
item.
Activity xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/login_background"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.frequentbuyer.ui.activity.ShoppingListListActivity" >
<ListView
android:id="@+id/shoppingListsListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/addShoppingListButton"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:cacheColorHint="#00000000" >
</ListView>
<Button
android:id="@+id/addShoppingListButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/shoppingListsListView"
android:layout_alignParentBottom="true"
android:layout_alignRight="@+id/shoppingListsListView"
android:text="@string/add_shopping_list" />
</RelativeLayout>
List item xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/list_item_gradient" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:background="@drawable/border_rectangle_shape"
android:orientation="horizontal" >
<TextView
android:id="@+id/shoppingListName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/shoppingListItemsNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</RelativeLayout>
Activity class
package com.frequentbuyer.ui.activity;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import roboguice.inject.ContentView;
import roboguice.inject.InjectExtra;
import roboguice.inject.InjectView;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import com.frequentbuyer.R;
import com.frequentbuyer.exception.DataAccessException;
import com.frequentbuyer.model.ShoppingList;
import com.frequentbuyer.model.User;
import com.frequentbuyer.service.contract.IShoppingListService;
import com.frequentbuyer.ui.adapters.ShoppingListListViewAdapter;
import com.google.inject.Inject;
@ContentView(R.layout.activity_shoppinglist_list)
public class ShoppingListListActivity extends AbstractBaseActivity {
/* shopping list list activity UI components */
@InjectView(R.id.shoppingListsListView)
private ListView shoppingListsListView;
@InjectView(R.id.addShoppingListButton)
private Button addShoppingListButton;
/* shopping list list activity injected services */
@Inject
private IShoppingListService shoppingListService;
/* shopping list list activity received extras */
// received from login activity
@InjectExtra(ActivityParameterNames.AUTHENTICATED_USER)
User loggedInUser;
private List<ShoppingList> allShoppingLists;
/* activity events */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initializeShoppingListView();
// add listeners
addListeners();
registerForContextMenu(shoppingListsListView);
}
@Override
public void onBackPressed() {
showExitDialog();
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
if (view.getId() == R.id.shoppingListsListView) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
menu.setHeaderTitle(allShoppingLists.get(info.position).getName());
menu.add(Menu.NONE, 0, 0, R.string.delete_shopping_list);
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
try {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
long shoppingListToDeleteId = info.id;
shoppingListService.deleteShoppingList(this, shoppingListToDeleteId);
reloadCurrentActivity();
} catch (DataAccessException e) {
showErrorMessageDialog(e.getLocalizedMessage());
}
return true;
}
/* activity methods */
private void initializeShoppingListView() {
try {
allShoppingLists = shoppingListService.getAllShoppingListsForUser(ShoppingListListActivity.this, loggedInUser.getId());
// pass context and data to the custom shopping list list adapter
ShoppingListListViewAdapter shoppingListListViewAdapter = new ShoppingListListViewAdapter(this, allShoppingLists);
// set shopping list list adapter
shoppingListsListView.setAdapter(shoppingListListViewAdapter);
} catch (DataAccessException e) {
showErrorMessageDialog(e.toString());
}
}
private void addListeners() {
shoppingListsListView.setOnItemClickListener(shoppingListListItemOnClickListener);
addShoppingListButton.setOnClickListener(addShoppingListButtonOnClickListener);
}
/* activity listeners */
private OnItemClickListener shoppingListListItemOnClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long shoppingListId) {
try {
HashMap<String, Serializable> activityParametersMap = new HashMap<String, Serializable>();
activityParametersMap.put(ActivityParameterNames.SELECTED_SHOPPING_LIST, shoppingListService.getShoppingListById(ShoppingListListActivity.this, shoppingListId));
activityParametersMap.put(ActivityParameterNames.AUTHENTICATED_USER, loggedInUser);
startAnotherActivity(ShoppingListListActivity.this, EditShoppingListActivity.class, activityParametersMap);
} catch (DataAccessException e) {
showErrorMessageDialog(e.getLocalizedMessage());
}
}
};
View.OnClickListener addShoppingListButtonOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
HashMap<String, Serializable> shoppingListListActivityParametersMap = new HashMap<String, Serializable>();
shoppingListListActivityParametersMap.put(ActivityParameterNames.AUTHENTICATED_USER, loggedInUser);
ShoppingListListActivity.startAnotherActivity(ShoppingListListActivity.this, CreateShoppingListActivity.class, shoppingListListActivityParametersMap);
}
};
}
Custom adapter class
package com.frequentbuyer.ui.adapters;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.frequentbuyer.R;
import com.frequentbuyer.model.ShoppingList;
public class ShoppingListListViewAdapter extends ArrayAdapter<ShoppingList> {
private final Context context;
private final List<ShoppingList> shoppingLists;
public ShoppingListListViewAdapter(Context context, List<ShoppingList> shoppingLists) {
super(context, R.layout.shoppinglist_list_item, shoppingLists);
this.context = context;
this.shoppingLists = shoppingLists;
}
@SuppressLint("ViewHolder")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// create inflater
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// get rowView from inflater
View rowView = inflater.inflate(R.layout.shoppinglist_list_item, parent, false);
// get the two text view from the rowView
TextView shoppingListNameView = (TextView) rowView.findViewById(R.id.shoppingListName);
// set the text for textView
shoppingListNameView.setText(shoppingLists.get(position).getName());
// get the two text view from the rowView
TextView shoppingListItemNumberView = (TextView) rowView.findViewById(R.id.shoppingListItemsNumber);
// set the text for textView
int shoppingListSize = shoppingLists.get(position).getShoppingItems().size();
shoppingListItemNumberView.setText("(" + shoppingListSize + " item" + (shoppingListSize == 1 ? ")" : "s)"));
// return rowView
return rowView;
}
@Override
public long getItemId(int position) {
return shoppingLists.get(position).getId();
}
}
In some previous version of the app I used ListView
in the same way on my phone without any problems, and now it is causing my app to crash.
Any idea why this is happening?
I used USB debugging, and found NullPointerException in logcat. It was thrown in getItemId
method of my custom adapter, because my entities had null value for id field in database, for some reason. I defined id fields by using ORMLite with:
@DatabaseField(generatedId = true) private Long id;
I changed type of id fields from Long to int and reinstalled app on phone and it worked, id fields were populated.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.