在通过 ArrayList 将数据添加到 sqlite 数据库后,我试图创建一个回收器视图,但是在从数据库中获取数据并通过适配器显示回收器视图时出现空指针异常。
这是我的内部数据库的代码:
package com.packr.database;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import com.packr.classes.Shipment;
import com.packr.logging.L;
import java.util.ArrayList;
import java.util.Date;
/**
* Created by arindam.paaltao on 04-Aug-15.
*/
public class DBShipments {
public static final int MY_SHIPMENTS = 0;
private ShipmentsHelper mHelper;
private SQLiteDatabase mDatabase;
public DBShipments(Context context) {
mHelper = new ShipmentsHelper(context);
mDatabase = mHelper.getWritableDatabase();
}
public void insertShipment(ArrayList<Shipment> shipmentArrayList, boolean clearPrevious) {
if (clearPrevious) {
deleteShipments();
}
//create a sql prepared statement
String sql = "INSERT INTO " + (ShipmentsHelper.TABLE_MY_SHIPMENTS) + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?);";
//compile the statement and start a transaction
SQLiteStatement statement = mDatabase.compileStatement(sql);
mDatabase.beginTransaction();
for (int i = 0; i < shipmentArrayList.size(); i++) {
Shipment current = shipmentArrayList.get(i);
statement.clearBindings();
//for a given column index, simply bind the data to be put inside that index
statement.bindString(2,current.getRecipientName());
statement.bindString(3,current.getRecipientContact());
statement.bindString(4, current.getItemQuantity());
statement.bindString(5, current.getItemType());
statement.bindString(6, current.getDeliveryType());
statement.bindString(7, current.getStreetNo());
statement.bindString(8, current.getRoute());
statement.bindString(9, current.getState());
statement.bindString(10, current.getCity());
statement.bindString(11, current.getPostalCode());
statement.bindDouble(12,current.getLatitude());
statement.bindDouble(13, current.getLongitude());
statement.execute();
}
//set the transaction as successful and end the transaction
L.m("inserting entries " + shipmentArrayList.size() + new Date(System.currentTimeMillis()));
mDatabase.setTransactionSuccessful();
mDatabase.endTransaction();
}
public ArrayList<Shipment> readShipments() {
ArrayList<Shipment> shipmentArrayList = new ArrayList<>();
//get a list of columns to be retrieved, we need all of them
String[] columns = {
ShipmentsHelper.COLUMN_ID,
ShipmentsHelper.COLUMN_RECIPIENT_NAME,
ShipmentsHelper.COLUMN_RECIPIENT_CONTACT,
ShipmentsHelper.COLUMN_ITEM_QUANTITY,
ShipmentsHelper.COLUMN_ITEM_TYPE,
ShipmentsHelper.COLUMN_DELIVERY_TYPE,
ShipmentsHelper.COLUMN_STREET_NO,
ShipmentsHelper.COLUMN_ROUTE,
ShipmentsHelper.COLUMN_LOCALITY,
ShipmentsHelper.COLUMN_CITY,
ShipmentsHelper.COLUMN_POSTAL_CODE,
ShipmentsHelper.COLUMN_LATITUDE,
ShipmentsHelper.COLUMN_LONGITUDE
};
Cursor cursor = mDatabase.query((ShipmentsHelper.TABLE_MY_SHIPMENTS), columns, null, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
L.m("loading entries " + cursor.getCount() + new Date(System.currentTimeMillis()));
do {
//create a new movie object and retrieve the data from the cursor to be stored in this movie object
Shipment shipment = new Shipment();
//each step is a 2 part process, find the index of the column first, find the data of that column using
//that index and finally set our blank movie object to contain our data
shipment.setRecipientName(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_RECIPIENT_NAME)));
shipment.setRecipientContact(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_RECIPIENT_CONTACT)));
shipment.setItemQuantity(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_ITEM_QUANTITY)));
shipment.setItemType(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_ITEM_TYPE)));
shipment.setDeliveryType(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_DELIVERY_TYPE)));
shipment.setStreetNo(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_STREET_NO)));
shipment.setRoute(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_ROUTE)));
shipment.setCity(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_LOCALITY)));
shipment.setState(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_CITY)));
shipment.setPostalCode(cursor.getString(cursor.getColumnIndex(ShipmentsHelper.COLUMN_POSTAL_CODE)));
shipment.setLatitude(cursor.getDouble(cursor.getColumnIndex(ShipmentsHelper.COLUMN_LATITUDE)));
shipment.setLongitude(cursor.getDouble(cursor.getColumnIndex(ShipmentsHelper.COLUMN_LONGITUDE)));
//add the task to the list of task objects which we plan to return
shipmentArrayList.add(shipment);
}
while (cursor.moveToNext());
}
return shipmentArrayList;
}
public void deleteShipments() {
mDatabase.delete((ShipmentsHelper.TABLE_MY_SHIPMENTS), null, null);
}
private static class ShipmentsHelper extends SQLiteOpenHelper {
public static final String TABLE_MY_SHIPMENTS = "my_shipments";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_RECIPIENT_NAME = "recipientName";
public static final String COLUMN_RECIPIENT_CONTACT = "recipientContact";
public static final String COLUMN_ITEM_QUANTITY = "itemQuantity";
public static final String COLUMN_ITEM_TYPE = "itemType";
public static final String COLUMN_DELIVERY_TYPE = "deliveryType";
public static final String COLUMN_STREET_NO = "streetNo";
public static final String COLUMN_ROUTE = "route";
public static final String COLUMN_LOCALITY = "locality";
public static final String COLUMN_CITY = "city";
public static final String COLUMN_POSTAL_CODE = "postalCode";
public static final String COLUMN_LATITUDE = "latitude";
public static final String COLUMN_LONGITUDE = "longitude";
private static final String CREATE_TABLE_MY_SHIPMENTS = "CREATE TABLE " + TABLE_MY_SHIPMENTS + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
COLUMN_RECIPIENT_NAME + " TEXT," +
COLUMN_RECIPIENT_CONTACT + " TEXT," +
COLUMN_ITEM_QUANTITY + " TEXT," +
COLUMN_ITEM_TYPE + " TEXT," +
COLUMN_DELIVERY_TYPE + " TEXT," +
COLUMN_STREET_NO + " TEXT," +
COLUMN_ROUTE + " TEXT," +
COLUMN_LOCALITY + " TEXT," +
COLUMN_CITY + " TEXT," +
COLUMN_POSTAL_CODE + " TEXT," +
COLUMN_LATITUDE + " TEXT," +
COLUMN_LONGITUDE + " TEXT" +
");";
private static final String DB_NAME = "my_shipments_db";
private static final int DB_VERSION = 1;
private Context mContext;
public ShipmentsHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(CREATE_TABLE_MY_SHIPMENTS);
L.m("create table shipments executed");
} catch (SQLiteException exception) {
L.t(mContext, exception + "");
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try {
L.m("upgrade table shipments executed");
db.execSQL(" DROP TABLE " + TABLE_MY_SHIPMENTS + " IF EXISTS;");
onCreate(db);
} catch (SQLiteException exception) {
L.t(mContext, exception + "");
}
}
}
}
如果在此活动中它不为空,我已经初始化了回收器视图并从内部数据库中获取回收器视图:
package com.packr.activities;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.packr.R;
import com.packr.adapters.ShipmentsAdapter;
import com.packr.classes.Packr;
import com.packr.classes.SharedPreferenceClass;
import com.packr.classes.Shipment;
import com.packr.database.DBShipments;
import com.packr.logging.L;
import java.util.ArrayList;
public class MyShipmentsActivity extends AppCompatActivity {
private static final String STATE_SHIPMENTS = "state_shipments";
private Toolbar toolbar;
private RecyclerView mRecyclerView;
private ShipmentsAdapter mShipmentAdapter;
private SharedPreferenceClass preferenceClass;
private Button addShipment;
private LinearLayout askForPickup;
private MyShipmentsActivity activity;
private ArrayList<Shipment> shipmentArrayList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_shipments);
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("My shipments");
setSupportActionBar(toolbar);
initialize();
onClick();
if (savedInstanceState != null) {
//if this fragment starts after a rotation or configuration change, load the existing movies from a parcelable
shipmentArrayList = savedInstanceState.getParcelableArrayList(STATE_SHIPMENTS);
} else {
shipmentArrayList = Packr.getWritableDatabase().readShipments();
if (shipmentArrayList.isEmpty()) {
L.T(getApplicationContext(), "No shipments found");
}
}
mRecyclerView = (RecyclerView) findViewById(R.id.shipments_recycler_view);
mShipmentAdapter = new ShipmentsAdapter(getApplicationContext(), activity);
mRecyclerView.setAdapter(mShipmentAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mShipmentAdapter.setShipmentArrayList(shipmentArrayList);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_my_shipments, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
return super.onOptionsItemSelected(item);
}
public void initialize() {
addShipment = (Button) findViewById(R.id.add_shipment);
askForPickup = (LinearLayout) findViewById(R.id.askForPickup);
}
public void onClick() {
addShipment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!shipmentArrayList.isEmpty()) {
Intent intent = new Intent(MyShipmentsActivity.this, DeliveryAddressSearchActivity.class);
startActivity(intent);
} else {
Intent intent = new Intent(MyShipmentsActivity.this, PickupAddressSearchActivity.class);
startActivity(intent);
}
}
});
askForPickup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (shipmentArrayList.isEmpty()) {
L.T(getApplicationContext(), "No shipments found");
}
}
});
}
}
我想将此活动中的数据插入到内部数据库中。我已经在此处初始化了适配器,但是当我尝试将 Arraylist 设置为此处的适配器时出现空指针异常。
这是活动的代码:
package com.packr.activities;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TextInputLayout;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import com.avast.android.dialogs.fragment.SimpleDialogFragment;
import com.avast.android.dialogs.iface.ISimpleDialogListener;
import com.kbeanie.imagechooser.api.ChooserType;
import com.kbeanie.imagechooser.api.ChosenImage;
import com.kbeanie.imagechooser.api.ImageChooserListener;
import com.kbeanie.imagechooser.api.ImageChooserManager;
import com.packr.R;
import com.packr.adapters.ShipmentsAdapter;
import com.packr.classes.Packr;
import com.packr.classes.Shipment;
import com.packr.database.DBShipments;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
public class ItemDetailsActivity extends AppCompatActivity implements ISimpleDialogListener, ImageChooserListener {
private Toolbar toolbar;
private ImageChooserManager imageChooserManager;
private SeekBar seekBar;
private RadioGroup radioGroup;
private TextView addImage;
private Bitmap myBitmap;
private ShipmentsAdapter mShipmentAdapter;
private ImageView itemImage;
private TextInputLayout itemDescriptionText, quantityText, valueOfItemText;
private EditText itemDescription, quantity, valueOfItem;
private TextView weightUnit, weightValue, selectWeight;
private ArrayList<Shipment> shipmentArrayList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_details);
initialize();
onClick();
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Item details");
setSupportActionBar(toolbar);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.parcelRadioButton) {
weightUnit.setText("kg");
selectWeight.setText("Select weight of item");
if (seekBar.getVisibility() == View.GONE) {
seekBar.setVisibility(View.VISIBLE);
}
seekBar.setProgress(5);
weightValue.setText(String.valueOf(seekBar.getProgress()));
} else {
seekBar.setVisibility(View.GONE);
weightUnit.setText("gm");
selectWeight.setText("Permitted weight");
weightValue.setText("upto 500");
}
}
});
seekBar.setProgress(1);
seekBar.incrementProgressBy(5);
seekBar.setMax(15);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progress = progress / 5;
progress = progress * 5;
weightValue.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_item_details, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_done) {
if (validationCheck()) {
Shipment shipment = new Shipment();
shipment.setRecipientName(getIntent().getExtras().getString("recipientName"));
shipment.setRecipientContact(getIntent().getExtras().getString("recipientContact"));
shipment.setCity(getIntent().getExtras().getString("city"));
shipment.setState(getIntent().getExtras().getString("state"));
shipment.setStreetNo(getIntent().getExtras().getString("street"));
shipment.setPostalCode(getIntent().getExtras().getString("pincode"));
shipmentArrayList.add(shipment);
**mShipmentAdapter.setShipmentArrayList(shipmentArrayList);
Packr.getWritableDatabase().insertShipment(shipmentArrayList, true);**
Intent intent = new Intent(ItemDetailsActivity.this, MyShipmentsActivity.class);
startActivity(intent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void initialize() {
seekBar = (SeekBar) findViewById(R.id.seekBar);
weightUnit = (TextView) findViewById(R.id.weightUnit);
weightValue = (TextView) findViewById(R.id.weightValue);
radioGroup = (RadioGroup) findViewById(R.id.radioPackageSize);
selectWeight = (TextView) findViewById(R.id.selectWeight);
addImage = (TextView) findViewById(R.id.addImage);
itemImage = (ImageView) findViewById(R.id.item_image);
itemDescriptionText = (TextInputLayout) findViewById(R.id.item_description_text_input_layout);
quantityText = (TextInputLayout) findViewById(R.id.item_quantity_text_input_layout);
valueOfItemText = (TextInputLayout) findViewById(R.id.item_value_text_input_layout);
itemDescription = (EditText) findViewById(R.id.item_description_edit_text);
quantity = (EditText) findViewById(R.id.item_quantity_edit_text);
valueOfItem = (EditText) findViewById(R.id.item_value_edit_text);
}
public void onClick() {
addImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SimpleDialogFragment.createBuilder(getApplicationContext(), getSupportFragmentManager()).setTitle("Choose item image").setMessage(R.string.selectImage).setNegativeButtonText("Gallery").setPositiveButtonText("Camera").show();
}
});
}
public Boolean validationCheck() {
if (itemDescription.getText().length() == 0) {
itemDescriptionText.setErrorEnabled(true);
itemDescriptionText.setError("Please provide an item description");
} else if (quantity.getText().length() == 0) {
quantityText.setErrorEnabled(true);
quantityText.setError("Provide item quantity");
} else if (valueOfItem.getText().length() == 0) {
valueOfItemText.setErrorEnabled(true);
valueOfItemText.setError("Please provide value of item");
} else {
return true;
}
return false;
}
public void chooseImage() {
imageChooserManager = new ImageChooserManager(this,
ChooserType.REQUEST_PICK_PICTURE);
imageChooserManager.setImageChooserListener(this);
try {
imageChooserManager.choose();
} catch (Exception e) {
e.printStackTrace();
}
}
public void snapImage() {
imageChooserManager = new ImageChooserManager(this, ChooserType.REQUEST_CAPTURE_PICTURE);
imageChooserManager.setImageChooserListener(this);
try {
imageChooserManager.choose();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onNegativeButtonClicked(int i) {
chooseImage();
}
@Override
public void onNeutralButtonClicked(int i) {
}
@Override
public void onPositiveButtonClicked(int i) {
snapImage();
}
@Override
public void onImageChosen(ChosenImage chosenImage) {
myBitmap = BitmapFactory.decodeFile(chosenImage.getFileThumbnail());
runOnUiThread(new Runnable() {
public void run() {
itemImage.setImageBitmap(myBitmap);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK &&
(requestCode == ChooserType.REQUEST_PICK_PICTURE ||
requestCode == ChooserType.REQUEST_CAPTURE_PICTURE)) {
imageChooserManager.submit(requestCode, data);
}
}
@Override
public void onError(String s) {
}
}
这是我收到的错误消息:
Process: com.packr, PID: 11838
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.packr/com.packr.activities.MyShipmentsActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2190)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2239)
at android.app.ActivityThread.access$800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5047)
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:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.packr.adapters.ShipmentsAdapter.setShipmentArrayList(ShipmentsAdapter.java:72)
at com.packr.activities.MyShipmentsActivity.onCreate(MyShipmentsActivity.java:66)
at android.app.Activity.performCreate(Activity.java:5249)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2154)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2239)
at android.app.ActivityThread.access$800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5047)
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:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)