问题
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