问题
I am learning BaseAdapter. I have custom listview. I want to fill data in listview from database. I am getting error of Null Pointer. Here is my code.
DbTools.java
public class DbTools extends SQLiteOpenHelper {
public DbTools(Context context) {
super(context, "local.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table ashu(Name varchar, address varchar)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("Drop Table if Exists ashu");
onCreate(db);
}
public void InsertDb(String Name,String address) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("Name", Name);
cv.put("address", address);
db.insert("ashu", null, cv);
db.close();
}
public ArrayList<NameAddress> getAllData(){
ArrayList<NameAddress> dataFromDb = new ArrayList<NameAddress>();
String SQL = "Select Name, address from ashu";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(SQL, null);
if (cursor.moveToFirst()){
do{
NameAddress na = new NameAddress();
na.NamesDb = cursor.getString(0).toString();
na.AddressDb = cursor.getString(1).toString();
dataFromDb.add(na);
} while(cursor.moveToNext());
}
return dataFromDb;
}
}
This is my Adapter class in which I extended BaseAdapter
Adapter.java
public class Adapter extends BaseAdapter{
public ArrayList<NameAddress> result;
ListView lv;
private Context context;
DbTools dbTools = new DbTools(context);
private LayoutInflater inflater = null;
public Adapter(Context context,ArrayList<NameAddress> rslt){
rslt=result;
this.context=context;
inflater = (LayoutInflater)(this.context).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return result.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) {
final NameAddress tmpData = result.get(position);
Holder h = new Holder();
DbTools dbTools = new DbTools(context);
View rootView;
rootView = inflater.inflate(R.layout.row, null);
h.textView1 = (TextView) rootView.findViewById(R.id.mainText);
h.textView2 = (TextView) rootView.findViewById(R.id.subText);
h.textView1.setText(tmpData.NamesDb);
h.textView2.setText(tmpData.AddressDb);
return rootView;
}
class Holder{
public TextView textView1, textView2;
}
}
MainActivity.java
public class MainActivity extends Activity {
ListView mainList;
Button save;
EditText name,address;
DbTools dbTools = new DbTools(this);
ArrayList<NameAddress> addList;
private Adapter adpter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainList = (ListView)findViewById(R.id.mainList);
save = (Button)findViewById(R.id.button1);
name = (EditText)findViewById(R.id.nameEditText);
address = (EditText)findViewById(R.id.addressEditText);
save.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String tempName = name.getText().toString();
String tempAdd = address.getText().toString();
dbTools.InsertDb(tempName, tempAdd);
Toast.makeText(getApplicationContext(), "Added Successfully", Toast.LENGTH_SHORT).show();
name.setText("");
address.setText("");
}
});
addList = new ArrayList<NameAddress>();
addList = dbTools.getAllData();
adpter = new Adapter(this, addList);
adpter.notifyDataSetChanged();
mainList.setAdapter(adpter);
}
}
And I have model class
NameAddress.java
public class NameAddress {
String NamesDb;
String AddressDb;
}
And In my row.xml there are only two textviews
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.ashu.customlist.MainActivity" >
<EditText
android:id="@+id/nameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/name"
android:ems="10" android:inputType="text">
<requestFocus />
</EditText>
<EditText
android:id="@+id/addressEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/address"
android:ems="10" />
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/save" />
<ListView
android:id="@+id/mainList"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
LOG
08-26 17:12:30.874: W/dalvikvm(19002): threadid=1: thread exiting with uncaught exception (group=0x41ee3d88)
08-26 17:12:30.874: E/AndroidRuntime(19002): Exception
08-26 17:12:30.874: E/AndroidRuntime(19002): FATAL EXCEPTION: main
08-26 17:12:30.874: E/AndroidRuntime(19002): Process: com.ashu.customlist, PID: 19002
08-26 17:12:30.874: E/AndroidRuntime(19002): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ashu.customlist/com.ashu.customlist.MainActivity}: java.lang.NullPointerException
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2237)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2286)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.ActivityThread.access$800(ActivityThread.java:145)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1243)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.os.Handler.dispatchMessage(Handler.java:102)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.os.Looper.loop(Looper.java:136)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.ActivityThread.main(ActivityThread.java:5127)
08-26 17:12:30.874: E/AndroidRuntime(19002): at java.lang.reflect.Method.invokeNative(Native Method)
08-26 17:12:30.874: E/AndroidRuntime(19002): at java.lang.reflect.Method.invoke(Method.java:515)
08-26 17:12:30.874: E/AndroidRuntime(19002): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
08-26 17:12:30.874: E/AndroidRuntime(19002): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
08-26 17:12:30.874: E/AndroidRuntime(19002): at dalvik.system.NativeStart.main(Native Method)
08-26 17:12:30.874: E/AndroidRuntime(19002): Caused by: java.lang.NullPointerException
08-26 17:12:30.874: E/AndroidRuntime(19002): at com.ashu.customlist.Adapter.getCount(Adapter.java:31)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.widget.ListView.setAdapter(ListView.java:480)
08-26 17:12:30.874: E/AndroidRuntime(19002): at com.ashu.customlist.MainActivity.onCreate(MainActivity.java:55)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.Activity.performCreate(Activity.java:5231)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
08-26 17:12:30.874: E/AndroidRuntime(19002): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2201)
08-26 17:12:30.874: E/AndroidRuntime(19002): ... 11 more
回答1:
ISSUE
You are initializing DbTools dbTools = new DbTools(this); in variable declaration portion of your activity MainActivity.
SOLUTION
Move this line to onCreate
DbTools dbTools = new DbTools(this);
This line has to be inside one of the activity lifecycle methods, preferably in onCreate method. Unless the Context will be null
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DbTools dbTools = new DbTools(this);
}
ISSUE
adpter.notifyDataSetChanged();
mainList.setAdapter(adpter);
Both of these lines are not required to call at a time.
SOLUTION
Use this
mainList.setAdapter(adpter);the first time you are setting your adapter.And call
adpter.notifyDataSetChanged();when your dataset is changed.
ISSUE
You are initializing the below line also in your Adapter class at the variable declaration portion.
DbTools dbTools = new DbTools(context);
As the context variable is null you cant initialize this.
Another problem in the constructor is that you are saving the null result to the parameter rslt. Actually it should be in the other way.
SOLUTION
Update the adapter constructor like this.
DbTools dbTools;
public Adapter(Context context,ArrayList<NameAddress> rslt){
result = rslt; //this line is swapped
this.context=context;
dbTools = new DbTools(context);
inflater = (LayoutInflater)(this.context).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
Also no need to initialize DbTools in getView method
回答2:
change this with because you are accessing a variable context without assigning any value..
public class Adapter extends BaseAdapter {
public ArrayList<NameAddress> result;
ListView lv;
private Context context;
DbTools dbTools;
private LayoutInflater inflater = null;
public Adapter(Context context, ArrayList<NameAddress> rslt) {
result = rslt;
this.context = context;
dbTools = new DbTools(context);
inflater = (LayoutInflater) (this.context)
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return result.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) {
final NameAddress tmpData = result.get(position);
Holder h = new Holder();
DbTools dbTools = new DbTools(context);
View rootView;
rootView = inflater.inflate(R.layout.row, null);
h.textView1 = (TextView) rootView.findViewById(R.id.mainText);
h.textView2 = (TextView) rootView.findViewById(R.id.subText);
h.textView1.setText(tmpData.NamesDb);
h.textView2.setText(tmpData.AddressDb);
return rootView;
}
class Holder {
public TextView textView1, textView2;
}
}
来源:https://stackoverflow.com/questions/32224855/listview-with-baseadapter