Error when calling object - Android - java

I'm calling the object here.
public class TestDetails extends ListActivity {
protected TextView testNameText;
protected SQLiteDatabase db;
protected TextView testvalueText;
protected List<TestAction> actions;
protected TestItemAdapter adapter;
protected int testId;
protected int categoryId;
#Override
//adds options menu
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.list_search: onSearchRequested();
break;
}
return true;
}
//end of add options menu
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_details);
// Get the intent, verify the action and get the query
db = (new DatabaseHelper(this)).getWritableDatabase();
Intent intent1 = getIntent();
SimpleSearch SSearch = new SimpleSearch();
if (Intent.ACTION_SEARCH.equals(intent1.getAction())) {
String query = intent1.getStringExtra(SearchManager.QUERY);
SSearch.testSearch(query);
}
testId = getIntent().getIntExtra("EMPLOYEE_ID", 0);
SQLiteDatabase db = (new DatabaseHelper(this)).getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT emp._id, emp.firstName, emp.lastName, emp.title, emp.officePhone, emp.cellPhone, emp.email, emp.managerId, mgr.firstName managerFirstName, mgr.lastName managerLastName FROM employee emp LEFT OUTER JOIN employee mgr ON emp.managerId = mgr._id WHERE emp._id = ?",
new String[]{""+testId});
if (cursor.getCount() == 1)
{
cursor.moveToFirst();
testNameText = (TextView) findViewById(R.id.employeeName);
testNameText.setText(cursor.getString(cursor.getColumnIndex("firstName")) + " " + cursor.getString(cursor.getColumnIndex("lastName")));
actions = new ArrayList<TestAction>();
String officePhone = cursor.getString(cursor.getColumnIndex("officePhone"));
if (officePhone != null) {
actions.add(new TestAction("Call office", officePhone, TestAction.ACTION_CALL));
}
String cellPhone = cursor.getString(cursor.getColumnIndex("cellPhone"));
if (cellPhone != null) {
actions.add(new TestAction("Call mobile", cellPhone, TestAction.ACTION_CALL));
actions.add(new TestAction("SMS", cellPhone, TestAction.ACTION_SMS));
}
String email = cursor.getString(cursor.getColumnIndex("email"));
if (email != null) {
actions.add(new TestAction("Email", email, TestAction.ACTION_EMAIL));
}
categoryId = cursor.getInt(cursor.getColumnIndex("managerId"));
if (categoryId>0) {
actions.add(new TestAction("View manager", cursor.getString(cursor.getColumnIndex("managerFirstName")) + " " + cursor.getString(cursor.getColumnIndex("managerLastName")), TestAction.ACTION_VIEW));
}
cursor = db.rawQuery("SELECT count(*) FROM employee WHERE managerId = ?",
new String[]{""+testId});
cursor.moveToFirst();
int count = cursor.getInt(0);
if (count>0) {
actions.add(new TestAction("View direct reports", "(" + count + ")", TestAction.ACTION_REPORTS));
}
adapter = new TestItemAdapter();
setListAdapter(adapter);
}
}
class TestItemAdapter extends ArrayAdapter<TestAction> {
TestItemAdapter() {
super(TestDetails.this, R.layout.action_list_item, actions);
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
public boolean isEnabled(int position) {
return false;
}
public View getView(int position, View convertView, ViewGroup parent) {
TestAction action = actions.get(position);
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.action_list_item, parent, false);
TextView label = (TextView) view.findViewById(R.id.label);
label.setText(action.getLabel());
TextView data = (TextView) view.findViewById(R.id.data);
data.setText(action.getData());
return view;
}
}
}
This is the class from which I'm calling the object.(part of the class)
public class SimpleSearch extends ListActivity {
protected SQLiteDatabase db;
protected Cursor cursor;
protected ListAdapter adapter;
protected String query;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
db = (new DatabaseHelper(this)).getWritableDatabase();
// Get the intent, verify the action and get the query
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
testSearch(query);
}
else TestListAll();
}
But I'm getting a force close on running the application. Stack trace shows the error to be in SSearch.testSearch(query); statement. What am I missing here?
Stack trace:
app_vercode:1
device_model:umts_jordan
build_version:1.11.18
condition:1
processName:com.simple.search
pid:3529
uid:10063
tag:null
shortMsg:java.lang.NullPointerException
longMsg:java.lang.NullPointerException: Unable to start activity ComponentInfo{com.simple.search/com.simple.search.TestDetails}: java.lang.NullPointerException
stackTrace:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.simple.search/com.simple.search.TestDetails}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1664)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1680)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3703)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.simple.search.SimpleSearch.testSearch(SimpleSearch.java:68)
at com.simple.search.TestDetails.onCreate(TestDetails.java:59)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1628)
... 11 more

Most likely the line
String query = intent1.getStringExtra(SearchManager.QUERY);
Is assigning a null value to query - are you sure the correct extra is there? I usually get extras in this manner:
public static final String TAG = "MyActivity";
public static final String DATA_KEY = "DataKey";
public static final String MY_CUSTOM_ACTION = "MyCustomSearchAction";
public void onCreate(Bundle savedInstanceState) {
Intent intent1 = getIntent();
SimpleSearch SSearch = new SimpleSearch();
if (intent1.getAction().equals(MY_CUSTOM_ACTION)
&& intent1.hasExtra(SearchManager.QUERY)
&& intent.hasExtra(DATA_KEY)) {
String query = intent1.getStringExtra(SearchManager.QUERY);
DataObject data = intent1.getParcelableExtra(DATA_KEY);
if (query != null && data != null)
SSearch.testSearch(query, data);
else {
//invalid query
Log.d(TAG,"Activity started with invalid query data - closing");
this.finish();
return;
}
} else {
//Invalid Intent
Log.d(TAG,"Activity started with invalid intent - closing");
this.finish();
return;
}
}
A data object can look like this:
public class DataObject implements Parcelable {
public String someData;
public String someMoreData;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(someData);
dest.writeString(someMoreDate);
}
//Constructor for parceler
public DataObject(Parcel src) {
someData = src.readString();
someMoreData = src.readString();
}
public static final Parcelable.Creator<DataObject> CREATOR =
new Parcelable.Creator<DataObject>() {
public DataObject createFromParcel(Parcel in) {
return new DataObject(in);
}
public DataObject[] newArray(int size) {
return new DataObject[size];
}
};
}
To start your activity just go:
DataObject data = new DataObject();
data.someData = "test";
data.someMoreData = "test2";
Intent intent = new Intnent(this, MyActivity.class);
intent.setAction(MyActivity.MY_CUSTOM_ACTION);
intent.putExtra(MyActivity.DATA_KEY,data);
intent.putExtra(SearchManager.QUERY, "Query");
startActivity(intent);

Related

How to create delete method in SQLite for deleting single item not the whole checklist?

I'll post only relevant code.
This is Activity which adds checklist to database.
public class AddChecklist extends AppCompatActivity {
Button btnAddItem;
public LinearLayout linearLayout;
ArrayList<String> itemList;
ArrayList<String> stateList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_checklist);
btnAddItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addView();
}
});
}
public void addView() {
View checklistView = getLayoutInflater().inflate(R.layout.checklist_view, null, false);
EditText etChecklistItem = checklistView.findViewById(R.id.et_checklist_item);
etChecklistItem.requestFocus();
linearLayout.addView(checklistView);
ImageView imgDelete = checklistView.findViewById(R.id.img_delete);
imgDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeView(checklistView);
}
});
}
public void removeView(View view) {
linearLayout.removeView(view);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
DbHelper dbHelper = new DbHelper(getApplicationContext());
switch (item.getItemId()) {
case R.id.btn_save:
ChecklistHelper checklistHelper = new ChecklistHelper();
for (int i = 0; i < linearLayout.getChildCount(); i++) {
View v = linearLayout.getChildAt(i);
EditText etChecklistItem = v.findViewById(R.id.et_checklist_item);
CheckBox checkBox = v.findViewById(R.id.check_box);
if (checkBox.isChecked()) {
checklistHelper.setStatus("1");
} else
checklistHelper.setStatus("0");
itemList.add(etChecklistItem.getText().toString());
stateList.add(checklistHelper.getStatus());
}
StringBuilder stringBuilder = new StringBuilder();
for (String items : itemList) {
stringBuilder.append(items);
stringBuilder.append("\n");
}
StringBuilder stringBuilder1 = new StringBuilder();
for (String state : stateList) {
stringBuilder1.append(state);
stringBuilder1.append("\n");
}
String items = stringBuilder.toString();
String state = stringBuilder1.toString();
dbHelper.insertChecklist(state, items, DateTime.date(), DateTime.time(), System.currentTimeMillis());
finish();
break;
}
return true;
}
}
This is insert checklist method in SQLiteHelper class.
public boolean insertChecklist(String status, String content, String date, String time, long now){
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
ContentValues c = new ContentValues();
c.put(CHECKLIST_STATUS, status);
c.put(CHECKLIST_CONTENT, content);
c.put(CHECKLIST_DATE, date);
c.put(CHECKLIST_TIME, time);
c.put(CHECKLIST_NOW, now);
long id = sqLiteDatabase.insert(CHECKLIST_TABLE, null, c);
Log.d("check", "checklist inserted -> ID = " + id);
return true;
}
This is the delete method for deleting the whole checklist, not for individual items.
public void deleteChecklist(long id){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(CHECKLIST_TABLE, CHECKLIST_ID + " =? ", new String[] {String.valueOf(id)});
}
Here I want a method like above, but only for deleting selected item, like this image.. Look at this image.
look this image

App crashes after theme change (apparently caused by fragment)

My Main Activity has three tabs. Each tab is a fragment. Now if you change the theme (white and dark are available), the activity is being recreated so that the change takes effect. But the app crashes.
How I deal with the fragments:
if (savedInstanceState == null) {
pageadapter = new SectionsPageAdapter(getSupportFragmentManager());
rFragMore = new RoomlistFragmentMore();
rFragMyRooms = new RoomlistFragmentMyRooms();
rFragFavs = new RoomlistFragmentFavorites();
} else {
rFragMyRooms = (RoomlistFragmentMyRooms)pageadapter.getItem(0);
rFragFavs = (RoomlistFragmentFavorites)pageadapter.getItem(1);
rFragMore = (RoomlistFragmentMore)pageadapter.getItem(2);
pageadapter.clearAdapter();
pageadapter = new SectionsPageAdapter(getSupportFragmentManager());
}
How I set up the Adapter:
private void setupViewPager(ViewPager viewPager) {
pageadapter.addFragment(rFragMyRooms, getResources().getString(R.string.myrooms));
pageadapter.addFragment(rFragFavs, getResources().getString(R.string.favorites));
pageadapter.addFragment(rFragMore, getResources().getString(R.string.more));
viewPager.setAdapter(pageadapter);
}
My Adapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public void clearAdapter() {
mFragmentList.clear();
mFragmentTitleList.clear();
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
}
And the Error Log:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileInputStream android.content.Context.openFileInput(java.lang.String)' on a null object reference
at com.yannick.mychatapp.RoomlistFragmentMore.readFromFile(RoomlistFragmentMore.java:246)
at com.yannick.mychatapp.RoomlistFragmentMore.addRoomToList(RoomlistFragmentMore.java:121)
at com.yannick.mychatapp.RoomlistFragmentMore.access$000(RoomlistFragmentMore.java:46)
at com.yannick.mychatapp.RoomlistFragmentMore$1.onDataChange(RoomlistFragmentMore.java:79)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##16.0.4:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##16.0.4:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##16.0.4:55)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
EDIT: the code of RoomlistFragmentMore
public class RoomlistFragmentMore extends Fragment {
private ListView listView;
private List<HashMap<String, String>> listItems = new ArrayList<>();
private String raumname, theme;
private static String userID = "";
private SimpleAdapter adapter;
private DatabaseReference root = FirebaseDatabase.getInstance().getReference().getRoot().child("rooms");
private ArrayList<Room> raumliste = new ArrayList<>();
private TextView keinraumgefunden;
private String[] kat;
private static final String TAG = "RoomlistFragmentMore";
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.roomlist_fragment_more,container,false);
listView = view.findViewById(R.id.listView);
keinraumgefunden = view.findViewById(R.id.keinraumgefunden);
kat = getResources().getStringArray(R.array.categories);
theme = readFromFile("mychatapp_theme.txt");
adapter = new SimpleAdapter(getActivity(), listItems, R.layout.listlayout,
new String[]{"name", "kat", "lock", "newest"},
new int[]{R.id.raumname, R.id.raumkat, R.id.raumlock, R.id.raumdatum});
listView.setAdapter(adapter);
root.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
addRoomToList(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getActivity(), R.string.nodatabaseconnection, Toast.LENGTH_SHORT).show();
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int position = listView.getPositionForView(view);
String roomname = listItems.get(position).values().toArray()[0].toString();
Room room = findRoom(raumliste, roomname);
request_password(room, position);
}
});
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
if (raumliste.isEmpty()) {
keinraumgefunden.setText(R.string.noroomfound);
} else {
keinraumgefunden.setText("");
}
}
});
return view;
}
private void addRoomToList(DataSnapshot dataSnapshot) {
HashMap<String, String> raeume = new HashMap<>();
raumliste.clear();
for(DataSnapshot uniqueKeySnapshot : dataSnapshot.getChildren()){
String name = uniqueKeySnapshot.getKey();
for(DataSnapshot roomSnapshot : uniqueKeySnapshot.getChildren()){
Room room = roomSnapshot.getValue(Room.class);
room.setRaumname(name);
if (!room.getPasswd().equals(readFromFile("mychatapp_raum_" + name + ".txt"))) {
raeume.put(name, kat[Integer.parseInt(room.getCaty())]+"/"+"\uD83D\uDD12"+"/");
raumliste.add(room);
}
break;
}
}
listItems.clear();
Iterator it = raeume.entrySet().iterator();
while (it.hasNext()){
HashMap<String, String> resultsMap = new HashMap<>();
Map.Entry pair = (Map.Entry)it.next();
resultsMap.put("name", pair.getKey().toString());
String daten = pair.getValue().toString();
String caty = daten.substring(0, daten.indexOf("/"));
String lock = daten.substring(daten.indexOf("/")+1, daten.lastIndexOf("/"));
String time = daten.substring(daten.lastIndexOf("/")+1, daten.length());
String newestTime = "";
int index = 0;
resultsMap.put("kat", caty);
resultsMap.put("lock", lock);
resultsMap.put("newest", newestTime);
if (time.equals("")) {
listItems.add(resultsMap);
} else {
listItems.add(index, resultsMap);
}
}
adapter.notifyDataSetChanged();
}
private void request_password(final Room room, final int position) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.enter_room, null);
raumname = room.getRaumname();
userID = readFromFile("mychatapp_userid.txt");
final EditText input_field = view.findViewById(R.id.room_password);
AlertDialog.Builder builder;
if (theme.equals(getResources().getStringArray(R.array.themes)[1])) {
builder = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.AlertDialogDark));
} else {
builder = new AlertDialog.Builder(getActivity());
}
builder.setTitle(R.string.pleaseenterpassword);
builder.setView(view);
builder.setCancelable(false);
builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
View view = ((AlertDialog) dialogInterface).getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
dialogInterface.cancel();
}
});
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
Button b = alert.getButton(AlertDialog.BUTTON_POSITIVE);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (input_field.getText().toString().trim().equals(room.getPasswd())) {
Intent tabIntent = new Intent("tab");
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(tabIntent);
Intent intent = new Intent(getActivity(), ChatActivity.class);
intent.putExtra("room_name", room.getRaumname());
intent.putExtra("user_id",userID);
updateRoomList(position);
writeToFile(room.getPasswd(),"mychatapp_raum_" + raumname + ".txt");
alert.cancel();
startActivity(intent);
} else {
Toast.makeText(getActivity(), R.string.wrongpassword, Toast.LENGTH_SHORT).show();
}
}
});
}
});
alert.show();
}
public Room findRoom(ArrayList<Room> raumliste, String raumname) {
for (Room room : raumliste) {
if (room.getRaumname().equals(raumname)) {
return room;
}
}
return null;
}
public void writeToFile(String text, String datei) {
Context context = getActivity();
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput(datei, Context.MODE_PRIVATE));
outputStreamWriter.write(text);
outputStreamWriter.close();
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
public String readFromFile(String datei) {
Context context = getActivity();
String erg = "";
try {
InputStream inputStream = context.openFileInput(datei);
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (receiveString = bufferedReader.readLine()) != null ) {
stringBuilder.append(receiveString);
}
inputStream.close();
erg = stringBuilder.toString();
}
}
catch (FileNotFoundException e) {
Log.e("login activity", "File not found: " + e.toString());
} catch (IOException e) {
Log.e("login activity", "Can not read file: " + e.toString());
}
return erg;
}
private void updateRoomList(int position) {
listItems.remove(position);
adapter.notifyDataSetChanged();
}
}
The NullPointerException occured while onDataChange() was executed (you can see this by reading the stack trace). More specifically, readFromFile() needs a valid Context to open a file.
Since your app crashed we know that getActivity() did return null. How can this happen?
You add the ValueEventListener in onCreateView(). At this point in time, the Fragment has a valid Context (see the documentation for an explanation of the Lifecycle), so all is well for the moment.
But since you do not remove the ValueEventListener, it will continue to fire even if the Fragment is temporarily not attached to the Activity because the user swiped to the next page. The Fragment won't be garbage collected because you keep it in a list and reuse it.
This approach is basically ok if you implement null checks to avoid accessing the Activity, the Context or Views in general while they are not present. Of course, you could consider a stronger separation of the data and the View layer as suggested in this guide to app architecture

Android: CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0, no answers on the site

I have searched for the answer on this website, but I can't find. I can't run my app because of the error below. Please help!
MainActivity.java
public class MainActivity extends AppCompatActivity {
private MeusLivrosListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
prepararBotoes();
listarLivros();
prepararCampoBusca();
}
private void listarLivros() {
MeusLivrosDBManganer dbManganer = new MeusLivrosDBManganer(getApplicationContext());
List<Livro> livros = dbManganer.recuperarListaLivros();
adapter = new MeusLivrosListAdapter(livros, this);
ListView lista = (ListView) findViewById(R.id.listaDeLivros);
lista.setAdapter(adapter);
}
private void prepararBotoes() {
Button btnAdicionar = (Button) findViewById(R.id.btn_adicionar);
btnAdicionar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AdicionarActivity.class);
startActivity(intent);
}
});
}
private void prepararCampoBusca() {
EditText txtPesquisar = (EditText) findViewById(R.id.txt_pesquisar);
if (txtPesquisar != null) {
txtPesquisar.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (count < before) {
// Reseta a lista
adapter.resetData();
}
adapter.getFilter().filter(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
}
}
MeusLivrosDBManganer .java
public class MeusLivrosDBManganer {
private MeusLivrosDBHelper dbHelper;
public MeusLivrosDBManganer(Context ctx) {
dbHelper = new MeusLivrosDBHelper(ctx);
}
public Cursor recuperarLivros() {
String[] campos = {
MeusLivrosDBContract.Livro.COLUMN_NAME_ID,
MeusLivrosDBContract.Livro.COLUMN_NAME_TITULO,
MeusLivrosDBContract.Livro.COLUMN_NAME_AUTOR,
MeusLivrosDBContract.Livro.COLUMN_NAME_EDITORA
};
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c = db.query(MeusLivrosDBContract.Livro.TABLE_NAME, campos, null, null, null, null, null);
db.close();
return c;
}
public List<Livro> recuperarListaLivros() {
List<Livro> livros = new ArrayList<>();
Cursor c = this.recuperarLivros();
do {
Livro l = new Livro();
l.id = c.getInt(c.getColumnIndex(MeusLivrosDBContract.Livro.COLUMN_NAME_ID));
l.titulo = c.getString(c.getColumnIndex(MeusLivrosDBContract.Livro.COLUMN_NAME_TITULO));
l.autor = c.getString(c.getColumnIndex(MeusLivrosDBContract.Livro.COLUMN_NAME_AUTOR));
l.editora = c.getString(c.getColumnIndex(MeusLivrosDBContract.Livro.COLUMN_NAME_EDITORA));
livros.add(l);
}while (c.moveToNext());
return livros;
}
public boolean inserirLivro(Livro livro) {
ContentValues values = new ContentValues();
values.put(MeusLivrosDBContract.Livro.COLUMN_NAME_AUTOR, livro.autor);
values.put(MeusLivrosDBContract.Livro.COLUMN_NAME_EDITORA, livro.editora);
values.put(MeusLivrosDBContract.Livro.COLUMN_NAME_TITULO, livro.titulo);
SQLiteDatabase db = dbHelper.getWritableDatabase();
long resultado = db.insert(MeusLivrosDBContract.Livro.TABLE_NAME, null, values);
db.close();
return resultado != -1;
}
}
adapter MeusLivrosListAdapter
public class MeusLivrosListAdapter extends ArrayAdapter<Livro> implements Filterable {
private List<Livro> listaDeLivros;
private Context context;
private Filter livroFilter;
private List<Livro> listaDeLivrosOriginal;
public MeusLivrosListAdapter(List<Livro> planetList, Context ctx) {
super(ctx, R.layout.layout_lista_livros, planetList);
this.listaDeLivros = planetList;
this.context = ctx;
this.listaDeLivrosOriginal = planetList;
}
public int getCount() {
return listaDeLivros.size();
}
public Livro getItem(int position) {
return listaDeLivros.get(position);
}
public long getItemId(int position) {
return listaDeLivros.get(position).hashCode();
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
LivrosHolder holder = new LivrosHolder();
//Verifica se a view está nula
if (convertView == null) {
// recupera a view
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.layout_lista_livros, null);
//recupera os campos da view
TextView idLivro = (TextView) v.findViewById(R.id.idLivro);
TextView tituloLivro = (TextView) v.findViewById(R.id.tituloLivro);
holder.livroIDView = idLivro;
holder.livroTituloView = tituloLivro;
v.setTag(holder);
}
else
holder = (LivrosHolder) v.getTag();
Livro l = listaDeLivros.get(position);
holder.livroIDView.setText(String.valueOf(l.id));
holder.livroTituloView.setText(String.valueOf(l.titulo));
return v;
}
public void resetData() {
listaDeLivros = listaDeLivrosOriginal;
}
/* *********************************
* Usamos o padrão holder
* Isto deixa a view mais rápida, pois evita ficar procurando o componente
* **********************************/
private static class LivrosHolder {
public TextView livroIDView;
public TextView livroTituloView;
}
/*
* Criamos nosso filtro
*/
#Override
public Filter getFilter() {
if (livroFilter == null)
livroFilter = new LivroFilter();
return livroFilter;
}
private class LivroFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// Implementamos a lógica do filtro
if (constraint == null || constraint.length() == 0) {
//sem filtros, retorna a lista toda
results.values = listaDeLivrosOriginal;
results.count = listaDeLivrosOriginal.size();
}
else {
// Executamos a opração de filtragem
List<Livro> nLivroList = new ArrayList<>();
for (Livro p : listaDeLivros) {
if (p.titulo.toUpperCase().contains(constraint.toString().toUpperCase()))
nLivroList.add(p);
}
results.values = nLivroList;
results.count = nLivroList.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
// informamos ao adapter sobre a nova lista filtrada
if (results.count == 0)
notifyDataSetInvalidated();
else {
listaDeLivros = (List<Livro>) results.values;
notifyDataSetChanged();
}
}
}
}
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.juliosampaio.meuslivros/com.juliosampaio.meuslivros.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:68)
at com.juliosampaio.meuslivros.MeusLivrosDBManganer.recuperarListaLivros(MeusLivrosDBManganer.java:47)
at com.juliosampaio.meuslivros.MainActivity.listarLivros(MainActivity.java:33)
at com.juliosampaio.meuslivros.MainActivity.onCreate(MainActivity.java:27)
The main possible reason is your cursor doesn't have data inside, you can't be sure that until you check the condition, and you should always be aware that do loop executes once without checking any conditions, Then only after executing single time, It checks the condition.
So I suggest do not use do while loop while looping the cursor to prevent crashing,
It's always better doing like this
while (cursor.moveToNext()) {
...
}
OR
However if you want to use do while loop, Then you should check if (cursor.moveToFirst()) before looping like
if (cursor.moveToFirst()) {
do {
...
} while (cursor.moveToNext());
}

After clicking the selected button,applicaton has stopped-shows logcat error

In my apps,i will provide checkbox dynamically and above one button for get selected i am providing,if you click the button it has to fetch the checked data what we given in an listview.But right now after clicking button select,the application has stopped.
Mainactivity.java
public class MainActivity extends Activity implements FetchDataListener,OnClickListener
{
private static final int ACTIVITY_CREATE=0;
private ProgressDialog dialog;
ListView lv;
private List<Application> items;
private Button btnGetSelected;
//private ProjectsDbAdapter mDbHelper;
//private SimpleCursorAdapter dataAdapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_item);
//mDbHelper = new ProjectsDbAdapter(this);
//mDbHelper.open();
//fillData();
//registerForContextMenu(getListView());
lv =(ListView)findViewById(R.id.list);
btnGetSelected = (Button) findViewById(R.id.btnget);
btnGetSelected.setOnClickListener(this);
initView();
}
private void initView()
{
// show progress dialog
dialog = ProgressDialog.show(this, "", "Loading...");
String url = "http://dry-brushlands-3645.herokuapp.com/posts.json";
FetchDataTask task = new FetchDataTask(this);
task.execute(url);
//mDbHelper.open();
//Cursor projectsCursor = mDbHelper.fetchAllProjects();
//startManagingCursor(projectsCursor);
// Create an array to specify the fields we want to display in the list (only TITLE)
//String[] from = new String[]{ProjectsDbAdapter.KEY_TITLE};
// and an array of the fields we want to bind those fields to (in this case just text1)
//int[] to = new int[]{R.id.text1};
/* Now create a simple cursor adapter and set it to display
SimpleCursorAdapter projects =
new SimpleCursorAdapter(this, R.layout.activity_row, projectsCursor, from, to);
setListAdapter(projects);
*/
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
/*dataAdapter = new SimpleCursorAdapter(
this, R.layout.activity_row,
projectsCursor,
from,
to,
0);
setListAdapter(dataAdapter);
*/
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.activity_main, menu);
super.onCreateOptionsMenu(menu);
MenuInflater mi = getMenuInflater();
mi.inflate(R.menu.activity_main, menu);
return true;
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
createProject();
return super.onMenuItemSelected(featureId, item);
}
private void createProject() {
Intent i = new Intent(this, ProjectEditActivity.class);
startActivityForResult(i, ACTIVITY_CREATE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
initView();
}
#Override
public void onFetchComplete(List<Application> data)
{
// dismiss the progress dialog
if ( dialog != null )
dialog.dismiss();
// create new adapter
ApplicationAdapter adapter = new ApplicationAdapter(this, data);
// set the adapter to list
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
CheckBox chk = (CheckBox) view.findViewById(R.id.checkbox);
Application bean = items.get(position);
if (bean.isSelected()) {
bean.setSelected(false);
chk.setChecked(false);
} else {
bean.setSelected(true);
chk.setChecked(true);
}
}
});
}
// Toast is here...
private void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
#Override
public void onFetchFailure(String msg)
{
// dismiss the progress dialog
if ( dialog != null )
dialog.dismiss();
// show failure message
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
#Override
public void onClick(View v) {
StringBuffer sb = new StringBuffer();
// Retrive Data from list
for (Application bean : items) {
if (bean.isSelected()) {
sb.append(bean.getContent());
sb.append(",");
}
}
showAlertView(sb.toString().trim());
}
private void showAlertView(String str) {
AlertDialog alert = new AlertDialog.Builder(this).create();
if (TextUtils.isEmpty(str)) {
alert.setTitle("Not Selected");
alert.setMessage("No One is Seleceted!!!");
} else {
// Remove , end of the name
String strContactList = str.substring(0, str.length() - 1);
alert.setTitle("Selected");
alert.setMessage(strContactList);
}
alert.setButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.show();
}
#Override
public void onBackPressed() {
AlertDialog alert_back = new AlertDialog.Builder(this).create();
alert_back.setTitle("Quit?");
alert_back.setMessage("Are you sure want to Quit?");
alert_back.setButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert_back.setButton2("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.this.finish();
}
});
alert_back.show();
}
#Override
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
// TODO Auto-generated method stub
}
This is my adapter closs,Applicationadapter.java
public class ApplicationAdapter extends ArrayAdapter<Application>
{
private List<Application> items;
private LayoutInflater inflator;
public ApplicationAdapter(Context context, List<Application> items)
{
super(context, R.layout.activity_row, items);
this.items = items;
inflator = LayoutInflater.from(getContext());
}
#Override
public int getCount()
{
return items.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
//View v = convertView;
if ( convertView == null )
{
convertView = inflator.inflate(R.layout.activity_row, null);
LayoutInflater li = LayoutInflater.from(getContext());
//convertView = inflator.inflate(R.layout.app_custom_list, null);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.text1);
holder.chk = (CheckBox) convertView.findViewById(R.id.checkbox);
holder.chk
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton view,
boolean isChecked) {
int getPosition = (Integer) view.getTag();
items.get(getPosition).setSelected(view.isChecked());
}
});
convertView.setTag(holder);
convertView.setTag(R.id.text1, holder.text1);
convertView.setTag(R.id.checkbox, holder.chk);
}else {
holder = (ViewHolder) convertView.getTag();
}
Application app = items.get(position);
holder.chk.setTag(position);
holder.text1.setText(Html.fromHtml(items.get(position).getContent()));
holder.chk.setChecked(items.get(position).isSelected());
if ( app != null )
{
TextView titleText = (TextView) convertView.findViewById(R.id.titleTxt);
if ( titleText != null )
titleText.setText(Html.fromHtml(app.getContent()).toString());
//titleText.setText(app.getContent());
//holder.chk.setChecked(((View) Html.fromHtml(app.getContent())).isSelected());
}
return convertView;
}
static class ViewHolder {
public TextView text1;
public CheckBox chk;
}
//return convertView;
}
Here i mention my logcat error also.
06-04 10:07:49.857: E/AndroidRuntime(2454): FATAL EXCEPTION: main
06-04 10:07:49.857: E/AndroidRuntime(2454): java.lang.NullPointerException
06-04 10:07:49.857: E/AndroidRuntime(2454): at com.example.jsonandroid.MainActivity.onClick(MainActivity.java:174)
06-04 10:07:49.857: E/AndroidRuntime(2454): at android.view.View.performClick(View.java:4202)
06-04 10:07:49.857: E/AndroidRuntime(2454): at android.view.View$PerformClick.run(View.java:17340)
06-04 10:07:49.857: E/AndroidRuntime(2454): at android.os.Handler.handleCallback(Handler.java:725)
06-04 10:07:49.857: E/AndroidRuntime(2454): at android.os.Handler.dispatchMessage(Handler.java:92)
06-04 10:07:49.857: E/AndroidRuntime(2454): at android.os.Looper.loop(Looper.java:137)
06-04 10:07:49.857: E/AndroidRuntime(2454): at android.app.ActivityThread.main(ActivityThread.java:5039)
06-04 10:07:49.857: E/AndroidRuntime(2454): at java.lang.reflect.Method.invokeNative(Native Method)
06-04 10:07:49.857: E/AndroidRuntime(2454): at java.lang.reflect.Method.invoke(Method.java:511)
06-04 10:07:49.857: E/AndroidRuntime(2454): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
06-04 10:07:49.857: E/AndroidRuntime(2454): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
06-04 10:07:49.857: E/AndroidRuntime(2454): at dalvik.system.NativeStart.main(Native Method)
After clicking the btngetselected,apps has stopped
this is my Application.java
public class Application {
private String content;
private boolean selected;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
In my code,i am using asynctask for fetching data,here i attached that code also.
public class FetchDataTask extends AsyncTask<String, Void, String>
{
private final FetchDataListener listener;
private String msg;
public FetchDataTask(FetchDataListener listener)
{
this.listener = listener;
}
#Override
protected String doInBackground(String... params)
{
if ( params == null )
return null;
// get url from params
String url = params[0];
try
{
// create http connection
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
// connect
HttpResponse response = client.execute(httpget);
// get response
HttpEntity entity = response.getEntity();
if ( entity == null )
{
msg = "No response from server";
return null;
}
// get response content and convert it to json string
InputStream is = entity.getContent();
return streamToString(is);
}
catch ( IOException e )
{
msg = "No Network Connection";
}
return null;
}
#Override
protected void onPostExecute(String sJson)
{
if ( sJson == null )
{
if ( listener != null )
listener.onFetchFailure(msg);
return;
}
try
{
// convert json string to json object
JSONObject jsonObject = new JSONObject(sJson);
JSONArray aJson = jsonObject.getJSONArray("post");
// create apps list
List<Application> apps = new ArrayList<Application>();
for ( int i = 0; i < aJson.length(); i++ )
{
JSONObject json = aJson.getJSONObject(i);
Application app = new Application();
app.setContent(json.getString("content"));
// add the app to apps list
apps.add(app);
}
//notify the activity that fetch data has been complete
if ( listener != null )
listener.onFetchComplete(apps);
}
catch ( JSONException e )
{
e.printStackTrace();
msg = "Invalid response";
if ( listener != null )
listener.onFetchFailure(msg);
return;
}
}
/**
* This function will convert response stream into json string
*
* #param is
* respons string
* #return json string
* #throws IOException
*/
public String streamToString(final InputStream is) throws IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try
{
while ( (line = reader.readLine()) != null )
{
sb.append(line + "\n");
}
}
catch ( IOException e )
{
throw e;
}
finally
{
try
{
is.close();
}
catch ( IOException e )
{
throw e;
}
}
return sb.toString();
}
}
06-04 10:07:49.857: E/AndroidRuntime(2454): java.lang.NullPointerException
06-04 10:07:49.857: E/AndroidRuntime(2454): at com.example.jsonandroid.MainActivity.onClick(MainActivity.java:174)
This error is very clear , you have a nullPointerException at onClick, check this line: Application bean : items I think there's the null pointer.
Assuming onFetchComplete is what populates your data, and is called before
for (Application bean : items) {
is called, you need to populate your items there. So,
#Override
public void onFetchComplete(List<Application> data) {
this.items = data;
But without seeing all of your code it is hard to tell what is happening.
The below line inside onClick is the source for your problem:
for (Application bean : items) {
...
}
here "items" is not initialized. hence NullpointerException.
you must initialize it somewhere like this:
private ArrayList<Application> items = new ArrayList<Application>();
and then have some data in that list to carry out necessary operation.

Android ListView with SimpleCursorAdapter - CursorIndexOutOfBoundsException error

I have a ListView in AcitivityA that is populated using a custom SimpleCursorAdapter called RecipeAdapter. The adapter holds data from SQLite
There is a EditText view at the top of the ListView, that filters the listview as the user searches for a recipe. When a user clicks on a item in the filtered ListView, ActivityB starts.
This all works perfectly. However when the user presses the backbutton to resume ActivityB, I get the following error.
java.lang.RuntimeException: Unable to resume activity {ttj.android.quorn/ttj.android.quorn.RecipeActivity}:
java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#418ae5d8
To fix this problem, I modified the onResume() from:
...
c = db.getCursor();
adapter.changeCursor(c);
to
....
Cursor cursor = db.getCursor();
adapter.changeCursor(cursor);
I then get the following exception. In the Logcat, the problem arises with the getId() method in DBHelper. I have added c.moveToFirst() in this method, but this still doesn't solve the problem.
FATAL EXCEPTION: main
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 70
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:400)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at ttj.android.quorn.DBHelper.getId(DBHelper.java:224)
at ttj.android.quorn.RecipeActivity$RecipeHolder.populateFrom(RecipeActivity.java:650)
at ttj.android.quorn.RecipeActivity$RecipeAdapter.bindView(RecipeActivity.java:572)
at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:256)
at android.widget.AbsListView.obtainView(AbsListView.java:2214)
at android.widget.ListView.makeAndAddView(ListView.java:1774)
at android.widget.ListView.fillDown(ListView.java:672)
at android.widget.ListView.fillFromTop(ListView.java:732)
at android.widget.ListView.layoutChildren(ListView.java:1611)
at android.widget.AbsListView.onLayout(AbsListView.java:2044)
at android.view.View.layout(View.java:11418)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
at android.view.View.layout(View.java:11418)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
at android.view.View.layout(View.java:11418)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
at android.view.View.layout(View.java:11418)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
at android.view.View.layout(View.java:11418)
at android.view.ViewGroup.layout(ViewGroup.java:4224)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1628)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2585)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4507)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
Can anyone help me with my problem?
Here is my code:
In the onCreate, the cursor populate the ListView using c.getCursor and when the user filters the ListView via the EditText, the c.getFilterCursor is used.
public class RecipeActivity extends SherlockListActivity {
private DBHelper db = null;
private Cursor c = null;
private RecipeAdapter adapter = null;
ListView listContent;
private EditText filterText = null;
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.filter_list);
filterText = (EditText) findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
ListView listContent = getListView();
db = new DBHelper(this);
db.createDataBase();
db.openDataBase();
c = db.getCursor();
adapter = new RecipeAdapter(c);
listContent.setAdapter(adapter);
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
// Search for states whose names begin with the specified letters.
c = db.getFilterCursor(constraint);
return c;
}
});
startManagingCursor(c);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
filterText.removeTextChangedListener(filterTextWatcher);
db.close();
}
#SuppressWarnings("deprecation")
#Override
protected void onResume() {
super.onResume();
Cursor cursor = db.getCursor();
adapter.changeCursor(cursor);
}
#Override
protected void onPause() {
super.onPause();
adapter.notifyDataSetInvalidated();
adapter.changeCursor(null);
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
adapter.getFilter().filter(s);
}
};
RecipeAdapter inner class
class RecipeAdapter extends CursorAdapter {
#SuppressWarnings("deprecation")
public RecipeAdapter(Cursor c) {
super(RecipeActivity.this, c);
}
public void bindView(View row, Context arg1, Cursor arg2) {
RecipeHolder holder = (RecipeHolder) row.getTag();
holder.populateFrom(c, db);
}
public View newView(Context arg0, Cursor arg1, ViewGroup arg2) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.reciperow, arg2, false);
RecipeHolder holder = new RecipeHolder(row);
row.setTag(holder);
return (row);
}
static class RecipeHolder {
public TextView id = null;
private TextView name = null;
private TextView desc = null;
private TextView preptime = null;
private TextView cooktime = null;
private TextView serves = null;
private TextView calories = null;
private TextView fat = null;
private TextView fav = null;
RecipeHolder(View row) {
id = (TextView) row.findViewById(R.id.id);
name = (TextView) row.findViewById(R.id.recipe);
desc = (TextView) row.findViewById(R.id.desc);
preptime = (TextView) row.findViewById(R.id.preptime);
cooktime = (TextView) row.findViewById(R.id.cooktime);
serves = (TextView) row.findViewById(R.id.serving);
calories = (TextView) row.findViewById(R.id.calories);
fat = (TextView) row.findViewById(R.id.fat);
fav = (TextView) row.findViewById(R.id.fav);
}
void populateFrom(Cursor c, DBHelper r) {
id.setText(r.getId(c));
name.setText(r.getRecipe(c));
name.setTextColor(Color.parseColor("#CCf27c22"));
desc.setText(r.getDesc(c));
preptime.setText(r.getPrepTime(c) + ". ");
cooktime.setText(r.getCookTime(c) + " mins");
serves.setText(r.getServes(c));
calories.setText(r.getCalories(c));
fat.setText(r.getFat(c));
fav.setText(r.getFav(c));
DBHelper class
public Cursor getCursor() {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DATABASE_TABLE);
String[] columns = new String[] { KEY_ROWID, RECIPE, DESC, PREPTIME,
COOKTIME, SERVES, CALORIES, FAT, CATEGORY, FAV };
Cursor myCursor = queryBuilder.query(myDataBase, columns, null, null,
null, null, RECIPE + " ASC");
return myCursor;
}
public Cursor getFilterCursor(CharSequence constraint) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DATABASE_TABLE);
String[] columns = new String[] { KEY_ROWID, RECIPE, DESC, PREPTIME,
COOKTIME, SERVES, CALORIES, FAT, CATEGORY, FAV };
if (constraint == null || constraint.length() == 0) {
// Return the full list
return queryBuilder.query(myDataBase, columns, null, null, null,
null, RECIPE + " ASC");
} else {
String value = "%" + constraint.toString() + "%";
return myDataBase.query(DATABASE_TABLE, columns, "RECIPE like ? ",
new String[] { value }, null, null, null);
}
}
public String getId(Cursor c) {
c.moveToFirst();
return (c.getString(0));
}
public String getRecipe(Cursor c) {
return (c.getString(1));
}
public String getDesc(Cursor c) {
return (c.getString(2));
}
public String getPrepTime(Cursor c) {
return (c.getString(3));
}
public String getCookTime(Cursor c) {
return (c.getString(4));
}
public String getServes(Cursor c) {
return (c.getString(5));
}
public String getCalories(Cursor c) {
return (c.getString(6));
}
public String getFat(Cursor c) {
return (c.getString(7));
}
public String getCategory(Cursor c) {
return (c.getString(8));
}
public String getFav(Cursor c) {
return (c.getString(9));
}
#SuppressWarnings("deprecation")
Bad. You should get rid of the deprecation instead of hiding that :)
startManagingCursor(c);
Don't do that. That may have caused the requery on the already closed cursor. Simply remove that line.
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
// Search for states whose names begin with the specified letters.
c = db.getFilterCursor(constraint);
return c;
}
});
Don't overwrite your c here. Just return db.getFilterCursor(constraint); is what this should do.
Other things that may have a positive effect
#SuppressWarnings("deprecation")
public RecipeAdapter(Cursor c) {
super(RecipeActivity.this, c);
}
public RecipeAdapter(Cursor c) {
// no requeries and no observer required if you change the cursor yourself
super(RecipeActivity.this, c, 0)
}
Next one:
adapter.notifyDataSetInvalidated();
adapter.changeCursor(null);
// change to
adapter.changeCursor(null);
adapter.notifyDataSetChanged(); // maybe without this
As far as I understand the documentation notifyDataSetInvalidated() means that the data can't be valid afterwards ("Once invoked this adapter is no longer valid and should not report further data set changes.") and you need to create a new Adapter instance. Not sure though. Just doing notifyDataSetChanged() works fine. It might even be the case that doing adapter.changeCursor() will already implicitly do the change notification.
P.S.: c.MoveToFirst() is not required. The CursorAdapter will move the cursor to the required position.
You renamed your variable, as indicated here
....
Cursor cursor = db.getCursor();
adapter.changeCursor(cursor);
correct? But right after that you specify that you tried
c.moveToFirst()
So maybe you should set
c = cursor;
So that the rest of your code works?

Categories

Resources