ListView not being destroyed/deflated on orientation change - android

I've got this problem where when I change the orientation of my device, for some reason the on-screen representation of the ListView associated with my ListFragment is retained, and a new ListView is inflated beneath it. To give you some context, I am creating a very simple app whose purpose is to test some DAO objects I created. I would have preferred to post some screenshots depicting the behavior my app is experiencing, but unfortunately, my reputation is too low at the moment.
The best I could describe it would be that when I change the orientation of the device from portrait to landscape (and vice versa), it inflates a whole new ListView without deflating the previous one. I have been looking into this for a couple of days now, and quite honestly, I am stumped. Any help you guys could offer would be greatly appreciated.
Here is the code for the ListFragment:
package edu.uark.csce.mobile.healthyshopper;
import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
/**
* A fragment representing a list of Items.
* <p />
* <p />
* Activities containing this fragment MUST implement the {#link Callbacks}
* interface.
*/
public class ViewFragment extends ListFragment implements
LoaderCallbacks<Cursor> {
// Class Fields:
private static final String TAG = "healthyshopper.ViewFragment";
private static final int MAIN_DB_LOADER = 0;
// In the final application, any query to the main database needs to return
// at least these fields:
private final String[] NECESSARY_COLUMNS = { DAOContentProvider.FOOD_DES,
DAOContentProvider.FOOD_CALORIES, DAOContentProvider.FOOD_FAT,
DAOContentProvider.FOOD_CARBS, DAOContentProvider.FOOD_PROTEIN };
private final String FROM[] = {DAOContentProvider.FOOD_GROUP, DAOContentProvider.FOOD_DES,
DAOContentProvider.FOOD_MANUFAC, DAOContentProvider.FOOD_PROTEIN,
DAOContentProvider.FOOD_FAT, DAOContentProvider.FOOD_CARBS,
DAOContentProvider.FOOD_CALORIES, DAOContentProvider.FOOD_SERV_SIZE};
private final int TO[] = {R.id.fd_group, R.id.shrt_desc,
R.id.manufac, R.id.protein,
R.id.fat, R.id.carb,
R.id.cal, R.id.amt};
private int threadMode;
private int queryType;
private int foodGroupId;
private CursorLoader loader;
private SimpleCursorAdapter listAdapter;
// Preference Option Constants:
private int UI_THREAD = 0;
private int BRANCHED_THREAD = 1;
private int ALL_ROWS = 0;
private int SPECIFIC_FD_GROUP = 1;
private int LIMITED_ROWS = 2;
private OnFragmentInteractionListener mListener;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ViewFragment() {
}
/***************************************
* Life cycle callbacks:
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "in onCreate()");
setRetainInstance(true);
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
if(savedInstanceState == null){
listAdapter = new SimpleCursorAdapter(getActivity(), R.layout.list_node, null, FROM, TO, 0);
setListAdapter(listAdapter);
}
}
#Override
public void onStart(){
super.onStart();
}
#Override
public void onResume(){
super.onResume();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()
.getApplicationContext());
Log.d(TAG, preferences.getString("THREADING_MODE", "BLANK"));
//Load testing preferences:
threadMode = Integer.valueOf(preferences.getString("THREADING_MODE","0"));
queryType = Integer.valueOf(preferences.getString("QUERY_TYPE", "0"));
foodGroupId = Integer.valueOf(preferences.getString("FOOD_GROUP", "0")); // Default
if (threadMode == BRANCHED_THREAD) {
loader = (CursorLoader) getLoaderManager().initLoader(
MAIN_DB_LOADER, null, this);
} else {
String[] projection = null;
String selection = null;
if (queryType == SPECIFIC_FD_GROUP) {
Log.d(TAG, "Query Type: " + (getResources().getStringArray(R.array.query_type_select))[queryType]);
selection = DAOContentProvider.FOOD_GROUP + " = " + foodGroupId;
} else if (queryType == LIMITED_ROWS) {
projection = NECESSARY_COLUMNS;
}
/*This is for testing only. Ordinarily, you should NEVER perform Db operations on the UI thread.*/
listAdapter.swapCursor(getActivity().getContentResolver().query(
DAOContentProvider.CONTENT_URI, projection, selection, null, null));
}
}
#Override
public void onPause(){
super.onPause();
}
#Override
public void onStop(){
super.onStop();
}
#Override
public void onDestroyView(){
super.onDestroyView();
Log.e(TAG, "in onDestroyView()");
setListAdapter(null);
listAdapter.swapCursor(null);
listAdapter = null;
}
#Override
public void onDestroy(){
super.onDestroy();
}
#Override
public void onDetach(){
super.onDetach();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (null != mListener) {
}
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated to
* the activity and potentially other fragments contained in that activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(String id);
}
/**
* LoaderManager Callbacks;
*/
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case MAIN_DB_LOADER:
String[] projection = null;
String selection = null;
if (queryType == SPECIFIC_FD_GROUP) {
Log.d(TAG,
"Query Type: "
+ (getResources()
.getStringArray(R.array.query_type_select))[queryType]);
selection = DAOContentProvider.FOOD_GROUP + " = " + foodGroupId;
} else if (queryType == LIMITED_ROWS) {
projection = NECESSARY_COLUMNS;
}
return new CursorLoader(getActivity(),
DAOContentProvider.CONTENT_URI, projection, selection,
null, null);
default:
return null;
}
}
#Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
listAdapter.swapCursor(arg1);
listAdapter.notifyDataSetChanged();
}
#Override
public void onLoaderReset(Loader<Cursor> arg0) {
listAdapter.swapCursor(null);
listAdapter.notifyDataSetChanged();
}
}
And here is the code for its associated Activity:
package edu.uark.csce.mobile.healthyshopper;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class TestingActivity extends Activity implements ViewFragment.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testing);
ViewFragment list = new ViewFragment();
getFragmentManager().beginTransaction().add(R.id.test_layout, list).commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.testing, menu);
return true;
}
#Override
public void onFragmentInteraction(String id) {
// TODO Auto-generated method stub
}
}

You're using setRetainInstance(true); in your fragment. This makes the fragment to be retained and reused when the activity is re-created.
You can read more detailed description in this question: Further understanding setRetainInstance(true)

Related

How to refresh listview after click imagebutton in listview item from adapter?

please help me.
just want to know how can i refresh listview after i click imagebutton in my item.
here is my button onclick inside adapter..
buttonHeart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (arg0 != null) {
FragmentOne_DbAdapter database=new FragmentOne_DbAdapter(context);
database.open();
if(favorite.matches("0")) {
database.updateItemFavorite(_id,"1");
buttonHeart.setImageResource(R.drawable.heartred);
//Toast.makeText(arg0.getContext(),favorite,Toast.LENGTH_LONG).show();
}else if(favorite.matches("1")){
database.updateItemFavorite(_id, "0");
buttonHeart.setImageResource(R.drawable.heart);
//Toast.makeText(arg0.getContext(),favorite,Toast.LENGTH_LONG).show();
}
}
}
});
here is my complete adapter..
package com.magicstarme.virtualsongbook;
import android.content.Context;
import android.database.Cursor;
import android.media.Image;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.util.ArrayList;
/**
* Created by Joe on 6/29/2016.
*/
public class FragmentOne_Adapter extends CursorAdapter {
public FragmentOne_Adapter(Context context, Cursor c, int flags) {
super(context, c, flags);
// TODO Auto-generated constructor stub
}
#Override
public void bindView(View view, final Context context, Cursor cursor) {
// TODO Auto-generated method stub
TextView txtTitle = (TextView) view.findViewById(R.id.title);
TextView txtArtist = (TextView) view.findViewById(R.id.artist);
TextView txtVolume = (TextView) view.findViewById(R.id.volume);
TextView txtNumber = (TextView) view.findViewById(R.id.number);
final ImageButton buttonHeart = (ImageButton) view.findViewById(R.id.heart);
final int _id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
String title = cursor.getString(cursor.getColumnIndexOrThrow("title"));
String artist = cursor.getString(cursor.getColumnIndexOrThrow("artist"));
String volume = cursor.getString(cursor.getColumnIndexOrThrow("volume"));
final String favorite = cursor.getString(cursor.getColumnIndexOrThrow("favorite"));
String number = cursor.getString(cursor.getColumnIndexOrThrow("number"));
// Populate fields with extracted properties
txtTitle.setText(title);
txtArtist.setText(artist);
txtVolume.setText(volume);
txtNumber.setText(number);
if(favorite.matches("0")) {
buttonHeart.setImageResource(R.drawable.heart);
}else if(favorite.matches("1")){
buttonHeart.setImageResource(R.drawable.heartred);
}
buttonHeart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (arg0 != null) {
FragmentOne_DbAdapter database=new FragmentOne_DbAdapter(context);
database.open();
if(favorite.matches("0")) {
database.updateItemFavorite(_id,"1");
buttonHeart.setImageResource(R.drawable.heartred);
//Toast.makeText(arg0.getContext(),favorite,Toast.LENGTH_LONG).show();
}else if(favorite.matches("1")){
database.updateItemFavorite(_id, "0");
buttonHeart.setImageResource(R.drawable.heart);
//Toast.makeText(arg0.getContext(),favorite,Toast.LENGTH_LONG).show();
}
}
}
});
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// TODO Auto-generated method stub
return LayoutInflater.from(context).inflate(R.layout.fragment_fragment_one_slview, parent, false);
}
}
and here is my fragment..
package com.magicstarme.virtualsongbook;
import android.content.Context;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.FilterQueryProvider;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SimpleCursorAdapter;
import android.widget.TabHost;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.util.ArrayList;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link FragmentOne.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link FragmentOne#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentOne extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public FragmentOne() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment FragmentOne.
*/
// TODO: Rename and change types and number of parameters
public static FragmentOne newInstance(String param1, String param2) {
FragmentOne fragment = new FragmentOne();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
private FragmentOne_DbAdapter dbHelper;
private SimpleCursorAdapter dataAdapter;
private FragmentOne_Adapter FragmentOneAdapter;
ListView listView;
EditText player1ESearch;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_fragment_one, container, false);
TabHost host = (TabHost) rootView.findViewById(R.id.tabHost);
host.setup();
//Tab 1
TabHost.TabSpec spec = host.newTabSpec("SONG LIST");
spec.setContent(R.id.tab1);
spec.setIndicator("SONG LIST");
host.addTab(spec);
player1ESearch = (EditText) rootView.findViewById(R.id.player1Search);
listView = (ListView) rootView.findViewById(R.id.slPlayer1ListView);
dbHelper = new FragmentOne_DbAdapter(getActivity());
dbHelper.open();
//Clean all data
//dbHelper.deleteAllPlayer1();
//Add some data
dbHelper.insertPlayer1Songlist();
//Generate ListView from SQLite Database
displayPlayer1ListView();
ImageButton dplayer1ESearch=(ImageButton) rootView.findViewById(R.id.delete);
dplayer1ESearch.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
player1ESearch.setText("");
}
});
//Tab 2
spec = host.newTabSpec("NEW SONGS");
spec.setContent(R.id.tab2);
spec.setIndicator("NEW SONGS");
host.addTab(spec);
//Tab 3
spec = host.newTabSpec("FAVORITES");
spec.setContent(R.id.tab3);
spec.setIndicator("FAVORITES");
host.addTab(spec);
return rootView;
}
private void displayPlayer1ListView() {
Cursor cursor = dbHelper.fetchAllPlayer1();
FragmentOneAdapter = new FragmentOne_Adapter(getActivity(), cursor, 0);
listView.setAdapter(FragmentOneAdapter);
player1ESearch.addTextChangedListener(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) {
FragmentOneAdapter.getFilter().filter(s.toString());
}
});
FragmentOneAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return dbHelper.fetchPlayer1ByTitle(constraint.toString());
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
Simple call notifyDataSetChanged(); when you click in button for refresh your ListView
buttonHeart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
...
notifyDataSetChanged();
}
});
Basically your list view is connected with adapter. You need to notify this adapter to redraw the list view. Can you give more information where exactly your button click listener code is (in which class). If it is inside your adapter class (like I suppose) you can do something like this in your click listener code (some where inside the method public void onClick(View arg0) ) :
YourAdapterClassName.this.notifyDataSetChanged();
Update your adapter constructor to accept the Fragment as a parameter.
Something like :
public CustomAdapter(Context context, int id, HomeFragment fragment) {
this.fragment = fragment;
}
then you call methods using the fragment variable.
fragment.doSomething();
and in this method you can refresh the list using notifyDataSetChanged();

Android listview image button

First of all I'd like to thank all of you for helping me on numerous occasions before. SO have alwasy been my go-to place when faced with problems with programming.
This time however, I've been unable to find a solution to my problem...
I'm currently developing an android app that uses two activities (one main activity and a search activity).
Both of which hold a listview - the main activity has an already populated and fully functional listview and, the search activity has a populated one which seems to lack functionallity.
The listview is created in a custom adapter and contains an image button (toggling with a selector) and four textviews.
My problem is that when I toggle the image button in my search activity and then press back to get back to the main activity and finally go back to the search results, the image button is "unchecked".
Since the image button is a CRUCIAL point in both the design and the following functionallity, I'd really appriciate any kind of help.
package com.example.geostocks;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.json.JSONArray;
import org.json.JSONException;
import com.example.geostocks.R;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SearchView;
/* MainActivity.
* Made by: Joakim Bajoul Kakaei (881129-0298)
* Description: Creates and sets up the MainActivity programmatically.
* It is mainly associated with activity_main.xml, but uses the
* listview_layout.xml in connection to it.
*
* The idea was to keep the class as "clean" as possible and use
* multiple classes to help making coding and efficiency more easier.
*/
public class MainActivity extends Activity {
public Menu m; // Variable to store a menu-item as a public variable.
// This helps with data allocation; instead of declaring the
// searchview and searchmanager in the creation of the
// application,
// it will wait to do it once the user decides to start the
// search.
// an array to store all jsonobjects in.
private JSONArray companies;
// an arraylist to store multiple companyobjects created later.
private List<companiesBuilder> allCompanies = new ArrayList<companiesBuilder>();
/*
* (non-Javadoc)
*
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
/*
* executes the AsyncTask (top10). When the task is executed, it
* then gets the JSONArray which is bouncing around.
*/
companies = new top10().execute("DO IT!").get();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ExecutionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
/*
* The following snippet mainly creates the adapterobject and associates
* it with it's elements, context and layout.
*/
final ListView companyList = (ListView) findViewById(R.id.listView);
final companiesAdapter compAdp = new companiesAdapter(this,
R.layout.listview_layout);
System.out.println("after"); // debugging
/*
* a loop to create companyBuilder-objects from the JSONArray and then
* add those objects to an ArrayList (allCompanies).
*/
for (int i = 0; companies.length() > i; i++) {
System.out.println("companies-looper"); // debugging
System.out.println(companies.length()); // debugging
try {
System.out.println(companies.getJSONObject(i)); // debugging
allCompanies.add(new companiesBuilder(companies
.getJSONObject(i)));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* this loop goes through every company that has been built and adds it
* to the custom listview adapter.
*/
for (companiesBuilder built : allCompanies) {
compAdp.add(built);
}
companyList.setAdapter(compAdp);
}
/*
* (non-Javadoc)
*
* #see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
m = menu; // adds a reference to the variable m (menu).
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return (super.onCreateOptionsMenu(menu)); // returns the super for
// efficiency.
}
/*
* (non-Javadoc)
*
* #see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
openSearch(); // when searchbutton is clicked, it will start the
// opensearch method.
return true;
case R.id.action_settings:
// openSettings();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/*
* Written by: Joakim Bajoul Kakaei Description: Invoked when user presses
* search icon. Opens up the searchview in the menu.
*/
public void openSearch() {
/*
* snippet taken from
* http://developer.android.com/training/search/setup.html with some
* changes to it.
*/
SearchManager sm = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView sv = (SearchView) m.findItem(R.id.search).getActionView();
sv.setSearchableInfo(sm.getSearchableInfo(getComponentName()));
}
/*
* top10 (AsyncTask) Name: Joakim Bajoul Kakaei (881129-0298) Description:
* This class handles the connection between the JSONparser and the
* mainActivity using a different thread. It's mainly used to help with
* memory allocation as well as making sure the main-thread isn't too
* overloaded with too many assignments.
*/
private class top10 extends AsyncTask<String, String, JSONArray> {
#Override
protected JSONArray doInBackground(String... params) {
JSONparser jparser = new JSONparser();
companies = jparser.topCompanies();
System.out.println("background"); // debugging
return companies;
}
#Override
protected void onPostExecute(JSONArray jarr) {
System.out.println("onpost");
}
}
}
package com.example.geostocks;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ListView;
public class SearchActivity extends Activity {
JSONArray companies;
String query;
private List<companiesBuilder> allCompanies = new ArrayList<companiesBuilder>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
handleIntent(getIntent());
try {
/*
* executes the AsyncTask (top10). When the task is executed, it
* then gets the JSONArray which is bouncing around.
*/
companies = new searchList().execute("DO IT!").get();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ExecutionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
/*
* The following snippet mainly creates the adapterobject and associates
* it with it's elements, context and layout.
*/
final ListView companyList = (ListView) findViewById(R.id.listView_search);
final companiesAdapter compAdp = new companiesAdapter(this,
R.layout.listview_layout);
System.out.println("after"); // debugging
/*
* a loop to create companyBuilder-objects from the JSONArray and then
* add those objects to an ArrayList (allCompanies).
*/
for (int i = 0; companies.length() > i; i++) {
System.out.println("companies-looper"); // debugging
System.out.println(companies.length()); // debugging
try {
System.out.println(companies.getJSONObject(i)); // debugging
allCompanies.add(new companiesBuilder(companies
.getJSONObject(i)));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* this loop goes through every company that has been built and adds it
* to the custom listview adapter.
*/
for (companiesBuilder built : allCompanies) {
compAdp.add(built);
}
companyList.setAdapter(compAdp);
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
#Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
query = intent.getStringExtra(SearchManager.QUERY);
System.out.println(query);
// use the query to search your data somehow
}
}
private class searchList extends AsyncTask<String, String, JSONArray> {
#Override
protected JSONArray doInBackground(String... params) {
JSONparser jparser = new JSONparser();
companies = jparser.search(query);
System.out.println("background"); // debugging
return companies;
}
#Override
protected void onPostExecute(JSONArray jarr) {
System.out.println("onpost");
}
}
}
Custom listviewAdapter:
package com.example.geostocks;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
/* companiesAdapter.
* Made by: Joakim Bajoul Kakaei (881129-0298)
* Description: Since the listview we have decided to use has multiple objects on each row,
* the listview's adapter needs to be customized to meet those requirements.
* This class may be revised later on (to add or remove objects from the rowItemObjects).
*/
public class companiesAdapter extends ArrayAdapter<companiesBuilder> implements
OnClickListener {
private final int companiesBuilderResource;
private ArrayList<companiesBuilder> companies;
public companiesAdapter(final Context context,
final int companiesBuilderResource) {
super(context, 0);
this.companiesBuilderResource = companiesBuilderResource;
companies = new ArrayList<companiesBuilder>();
}
public void add(companiesBuilder row) {
companies.add(row);
notifyDataSetChanged();
}
#Override
public int getCount() {
return companies.size();
}
#Override
public companiesBuilder getItem(int i) {
return companies.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(final int position, final View convertView,
final ViewGroup parent) {
// We need to get the best view (re-used if possible) and then
// retrieve its corresponding rowItem, to optimize lookup efficiency.
final View view = getourView(convertView);
final rowItem rowItem = getrowItem(view);
// final companiesBuilder company = getItem(position);
final companiesBuilder row = companies.get(position);
// Setting up both the titleobject's with their corresponding variables
// (from the row-object).
rowItem.titleView_left.setText(row.getName());
rowItem.titleView_right.setText(row.getPrice());
// Setting up the subtitle's items will be a little bit tougher, since
// it requires
// some manipulating of the xml-data.
rowItem.subTitleView_left.setText(row.getSymbol());
/*
* If-clauses to change the right subtitle's color palette to make it
* easier for the user to distinguish increase and decrease.
*/
if (Double.parseDouble(row.getChange()) < 0) {
rowItem.subTitleView_right
.setTextColor(Color.parseColor("#E51400"));
rowItem.subTitleView_right.setText(row.getPercent() + "%" + " "
+ "( " + row.getChange() + ")");
} else if (Double.parseDouble(row.getChange()) > 0) {
rowItem.subTitleView_right
.setTextColor(Color.parseColor("#339933"));
rowItem.subTitleView_right.setText(row.getPercent() + "%" + " "
+ "( +" + row.getChange() + ")");
} else {
rowItem.subTitleView_right.setText(row.getPercent() + "%" + " "
+ "(" + row.getChange() + ")");
}
// Setting image view is simple enough...
rowItem.imageButton.setSelected(row.getSelected());
view.setOnClickListener(new OnClickListener() {
/*
* Add an onClickListener that is associated with view (view being
* every row).
*/
#Override
public void onClick(View v) {
new AlertDialog.Builder(getContext()).setTitle(row.getName())
.show();
}
});
rowItem.imageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View button) {
if (button.isSelected()) {
button.setSelected(false);
} else {
button.setSelected(true);
}
row.setSelect(view.isSelected());
}
});
return view;
}
private View getourView(final View convertView) {
// The ourView will be recycling / reusing the convertview if
// possible.
// Guess why? Exactly. CUZ WE LOOOOOOOOOOVE HAVING EFFICIENT CODE! <3
View ourView = null;
if (null == convertView) {
final Context context = getContext();
final LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ourView = inflater.inflate(companiesBuilderResource, null);
} else {
ourView = convertView;
}
return ourView;
}
private rowItem getrowItem(final View ourView) {
// Recycling and reusing tags and objects is the name of the game!
final Object tag = ourView.getTag();
rowItem rowItem = null;
/*
* Sets up the listview's rowitems with their corresponding listview
* items (textviews and images).
*/
if (null == tag || !(tag instanceof rowItem)) {
rowItem = new rowItem();
rowItem.titleView_right = (TextView) ourView
.findViewById(R.id.title_right);
rowItem.titleView_left = (TextView) ourView
.findViewById(R.id.title_left);
rowItem.subTitleView_left = (TextView) ourView
.findViewById(R.id.subtitle_left);
rowItem.subTitleView_right = (TextView) ourView
.findViewById(R.id.subtitle_right);
rowItem.imageButton = (ImageButton) ourView
.findViewById(R.id.add_button);
ourView.setTag(rowItem);
} else {
rowItem = (rowItem) tag;
}
return rowItem;
}
/*
* since views are recycled, these references will always be there to be
* reused. Again, it's all about optimization!
*/
private static class rowItem {
public TextView titleView_left;
public TextView titleView_right;
public TextView subTitleView_left;
public TextView subTitleView_right;
public ImageButton imageButton;
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
}
Selector for imagebutton
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_added_button" android:state_selected="true"/>
<item android:drawable="#drawable/ic_add_button" android:state_selected="false"/>
</selector>
Create model for companies (ex. Company class).
In Company class add property isSelected.
Fill array of companies from your JSONArray. Pass this array to ListView adapter.
In rowItem.imageButton.setOnClickListener update rowItem state (selected or not) in source array (array of companies, which was created from JSONArray).
Note: if you will save list row state, you should save this state in source array of your list adapter.
In MainActivity:
CompanyListAdapter adapter = new CompanyListAdapter(activity);
ArrayList<Company> companies = getCompaniesFromJsonArray();
for(Company company : companies){
adapter.add(company);
}
listView.setAdapter(adapter);
Company.java
package com.donvigo.TestCustomActionBar;
public class Company {
private String name;
private boolean isSelected;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}
}
CompanyListAdapter.java
package com.donvigo.TestCustomActionBar;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class CompanyListAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<Company> companies;
public CompanyListAdapter(Activity activity){
this.activity = activity;
companies = new ArrayList<Company>();
}
public void add(Company company){
companies.add(company);
notifyDataSetChanged();
}
#Override
public int getCount() {
return companies.size();
}
#Override
public Object getItem(int i) {
return companies.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder;
if(convertView == null){
convertView = activity.getLayoutInflater().inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.textViewName = (ImageView) convertView.findViewById(R.id.textViewName);
holder.rowImage = (ImageView) convertView.findViewById(R.id.rowImage);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
final Company row = companies.get(position);
// refresh state of your row image
holder.rowImage.setSelected(row.isSelected());
holder.rowImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (view.isSelected()) {
view.setSelected(false);
} else {
view.setSelected(true);
}
row.setSelected(view.isSelected());
}
});
return convertView;
}
private class ViewHolder{
public TextView textViewName;
public ImageView rowImage;
}
}
This is main idea. Also, if you will save row states in ListView permanently (not just 1 time when you download and show data from internet) - you have to save you companies data in database, or in another data storage (ex.: in text file) and next time when you open activity - restore previously saved companies list.
Seen your code, no where you are saving checked state of button. Point is when you navigate from MainActivity to SearchActivity your listview with custom adapter is populated and displayed, there you set some button, now once you navigate back to main activity from there you SearchAvtivity is destroyed and is completely redrawn when you navigate back. Hence you see every then fresh again.
If you want to retain checked state of button, you should save their latest state in preference and load it from there or you can keep global data variable for holding checked states of buttons so to retain it during entire life cycle of your applications.
Read about Activity life cycle and stack, when they are destroyed and created, this will throw you more insight over why this is happening.
hope it help.

Maintain filtered listview after rotation in android

I'm using customized ListView in android, and using search with customized EditText. When I search for a name, I will get the result using getFilter().filter(cs);. But, when I rotate, the ListView shows the full list (without filtering), then after a delay, it shows the filtered list.
When I rotate without filtering, it maintains the listview position.
So I have to maintain the filtered ListView when I rotate the screen.
Please help. Thanks in advance...
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Loader;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
#SuppressLint("HandlerLeak")
public class ContactsListActivity
extends Activity
implements LoaderManager.LoaderCallbacks<ArrayList<ListViewItem>> {
private LetterScrollListView mLSListView;
private ProgressBar mProgressBar;
private EditText mSearchText;
private ProgressBar mSearchProgressBar;
private LinearLayout mViewsLl;
private ContactAdapter mFullContactAdapter = null;
private ArrayList<ListViewItem> mFullContactsArrayList = null;
public boolean isSoftKeyOn = false;
public boolean isPortrait;
private long mLastTimeTextChanged = 0L;
private long mCurrentTime = 0L;
private Filter mFilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts_list);
RelativeLayout windowRl = (RelativeLayout) findViewById(R.id.window_RelativeLayout);
LinearLayout progressBarLl = (LinearLayout) windowRl.findViewById(R.id.progressBar_LinearLayout);
mViewsLl = (LinearLayout) windowRl.findViewById(R.id.views_LinearLayout);
mSearchText = (EditText) mViewsLl.findViewById(R.id.contact_SearchEditText);
mSearchProgressBar = (ProgressBar) mViewsLl.findViewById(R.id.search_ProgressBar);
mLSListView = (LetterScrollListView) mViewsLl.findViewById(R.id.contacts_LetterScrollListView);
mLSListView.setSearchText(mSearchText);
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
isPortrait = true;
} else {
isPortrait = false;
}
final View activityRootView = windowRl;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView()
.getHeight() - activityRootView.getHeight();
// if heightDiff > 100 pixels, its probably a keyboard...
if (heightDiff > 100) {
// Toast.makeText(getApplicationContext(), "Key ON",
// Toast.LENGTH_SHORT).show();
isSoftKeyOn = true;
} else {
// Toast.makeText(getApplicationContext(), "Key OFF",
// Toast.LENGTH_SHORT).show();
isSoftKeyOn = false;
mSearchText.clearFocus();
}
}
});
mSearchText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2,
int arg3) {
mCurrentTime = System.currentTimeMillis();
if( (mCurrentTime - mLastTimeTextChanged) <= USER_TYPE_DELAY ) {
mSearchInputHandler.removeMessages(WHAT_SEARCH);
}
// preparing message
Bundle bundle = new Bundle();
bundle.putCharSequence(USER_INPUT_KEY, cs);
Message message = mSearchInputHandler.obtainMessage(WHAT_SEARCH);
message.setData(bundle);
mSearchInputHandler.sendMessageDelayed(message, USER_TYPE_DELAY);
mLastTimeTextChanged = mCurrentTime;
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
// Create a progress bar to display while the list loads
mProgressBar = new ProgressBar(this);
mProgressBar.setIndeterminate(true);
progressBarLl.addView(mProgressBar);
getLoaderManager().initLoader(0, null, this).forceLoad();
}
#SuppressLint("HandlerLeak")
private final Handler mSearchInputHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
CharSequence cs = msg.getData().getCharSequence(USER_INPUT_KEY);
int what = msg.what;
switch(what) {
case WHAT_SEARCH:
// When user changed the Text after a delay
mSearchProgressBar.setVisibility(View.VISIBLE);
mFilter.filter(cs);
break;
}
}
};
public void removeSearchProgressBar() {
mSearchProgressBar.setVisibility(View.INVISIBLE);
}
/**
* Called when a new Loader needs to be created
*/
public Loader<ArrayList<ListViewItem>> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME
};
boolean showInvisible = false;
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
(showInvisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return new ContactArrayListLoader(this, uri, projection, selection, selectionArgs, sortOrder);
}
/**
* Called when a previously created loader has finished loading
*/
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {
mProgressBar.setVisibility(View.INVISIBLE);
if(mLSListView.getAdapter() == null) {
mFullContactsArrayList = data;
mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, mFullContactsArrayList);
mFilter = mFullContactAdapter.getFilter();
mLSListView.setAdapter(mFullContactAdapter);
}
}
/**
* Called when a previously created loader is reset, making the data unavailable
*/
public void onLoaderReset(Loader<ArrayList<ListViewItem>> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
//////mListView.setAdapter(new ContactAdapter(this, R.layout.contact_tuple, null));
mProgressBar.setVisibility(View.VISIBLE);
}
}
SOLVED
The problem is on the method
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {....}
On rotation/starting the app, the parameter data in this method is always the complete list and not the filtered list. So to get the filtered list on rotation, just create a static member
private static ArrayList<ListViewItem> sCurrentContactsArrayList = null;
and save before screen rotation like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if( TextUtils.isEmpty(mSearchText.getText()) ) {
sCurrentContactsArrayList = null;
} else {
sCurrentContactsArrayList = mFullContactAdapter.getCurrentItems();
}
}
also modify onLoadFinished():
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {
mProgressBar.setVisibility(View.INVISIBLE);
if(mLSListView.getAdapter() == null) {
ArrayList<ListViewItem> contactsAL = null;
if(sCurrentContactsArrayList == null) {
contactsAL = data;
} else {
contactsAL = sCurrentContactsArrayList;
}
mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, contactsAL, data);
if(mFilter == null) mFilter = mFullContactAdapter.getFilter();
mLSListView.setAdapter(mFullContactAdapter);
}
mSearchText.setVisibility(View.VISIBLE);
}

Saved data not being displayed when returned to activity

The saved data in my app stored using sqlite is not displayed when I go to a different activity deeper in the app and press the up button to go back to the original activity.
Here is the listfragment that is inflated by the listactivity.
Notice that I put the query in the onCreate to have it perform it again when going back to the activity.
package com.example.sample;
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockListFragment;
/**
* A list fragment representing a list of Courses. This fragment also supports
* tablet devices by allowing list items to be given an 'activated' state upon
* selection. This helps indicate which item is currently being viewed in a
* {#link CourseDetailFragment}.
* <p>
* Activities containing this fragment MUST implement the {#link Callbacks}
* interface.
*/
public class CourseListFragment extends SherlockListFragment {
SQLiteDatabase db;
DbHelper dbHelper;
boolean bool = false;
private static String courseName;
ArrayList<String> courseItems;
ArrayAdapter<String> adapter;
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
*/
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The current activated item position. Only used on tablets.
*/
private int mActivatedPosition = ListView.INVALID_POSITION;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {#link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
#Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public CourseListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DbHelper(getActivity());
db = dbHelper.getReadableDatabase();
courseItems = new ArrayList<String>();
int layout = (Build.VERSION.SDK_INT >= 11) ? android.R.layout.simple_list_item_activated_1
: android.R.layout.simple_list_item_1;
adapter = new ArrayAdapter<String>(getActivity(), layout, courseItems);
// TODO: replace with a real list adapter.
setListAdapter(adapter);
if (bool) {
String[] projection = { DbHelper.COURSE_NAME };
Cursor c = db.query(DbHelper.TABLE_NAME, projection, null, null,
null, null, null);
c.moveToFirst();
while (c.moveToNext()) {
courseName = c
.getString(c.getColumnIndex(DbHelper.COURSE_NAME));
courseItems.add(courseName);
}
c.close();
adapter.notifyDataSetChanged();
}
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState
.getInt(STATE_ACTIVATED_POSITION));
}
}
public void addCourse() {
String[] projection = { DbHelper.COURSE_NAME };
Cursor c = db.query(DbHelper.TABLE_NAME, projection, null, null, null,
null, null);
c.moveToFirst();
while (c.moveToNext()) {
courseName = c.getString(c.getColumnIndex(DbHelper.COURSE_NAME));
courseItems.add(courseName);
}
c.close();
adapter.notifyDataSetChanged();
bool = true;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException(
"Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
#Override
public void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(null);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(
activateOnItemClick ? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
public void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}
Edit updated for onoviewstaterestored
package com.example.sample;
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockListFragment;
/**
* A list fragment representing a list of Courses. This fragment also supports
* tablet devices by allowing list items to be given an 'activated' state upon
* selection. This helps indicate which item is currently being viewed in a
* {#link CourseDetailFragment}.
* <p>
* Activities containing this fragment MUST implement the {#link Callbacks}
* interface.
*/
public class CourseListFragment extends SherlockListFragment {
SQLiteDatabase db;
DbHelper dbHelper;
boolean bool = false;
private static String courseName;
ArrayList<String> courseItems;
ArrayAdapter<String> adapter;
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
*/
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The current activated item position. Only used on tablets.
*/
private int mActivatedPosition = ListView.INVALID_POSITION;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {#link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
#Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public CourseListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DbHelper(getActivity());
db = dbHelper.getReadableDatabase();
courseItems = new ArrayList<String>();
int layout = (Build.VERSION.SDK_INT >= 11) ? android.R.layout.simple_list_item_activated_1
: android.R.layout.simple_list_item_1;
adapter = new ArrayAdapter<String>(getActivity(), layout, courseItems);
// TODO: replace with a real list adapter.
setListAdapter(adapter);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState
.getInt(STATE_ACTIVATED_POSITION));
}
}
#Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
String[] projection = { DbHelper.COURSE_NAME };
Cursor c = db.query(DbHelper.TABLE_NAME, projection, null, null, null,
null, null);
c.moveToFirst();
while (c.moveToNext()) {
courseName = c.getString(c.getColumnIndex(DbHelper.COURSE_NAME));
courseItems.add(courseName);
}
c.close();
adapter.notifyDataSetChanged();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException(
"Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
#Override
public void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(null);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(
activateOnItemClick ? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
public void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}
I fixed it! I had to update the listview with the initially used addCourse method and then update it each time the activity resumes with the onViewStateRestored method. They both contain the same content in terms of what goes inside the method.
Here's the code to my working list fragment.
package com.example.sample;
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockListFragment;
/**
* A list fragment representing a list of Courses. This fragment also supports
* tablet devices by allowing list items to be given an 'activated' state upon
* selection. This helps indicate which item is currently being viewed in a
* {#link CourseDetailFragment}.
* <p>
* Activities containing this fragment MUST implement the {#link Callbacks}
* interface.
*/
public class CourseListFragment extends SherlockListFragment {
SQLiteDatabase db;
DbHelper dbHelper;
boolean bool = false;
private static String courseName;
ArrayList<String> courseItems;
ArrayAdapter<String> adapter;
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
*/
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The current activated item position. Only used on tablets.
*/
private int mActivatedPosition = ListView.INVALID_POSITION;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {#link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
#Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public CourseListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DbHelper(getActivity());
db = dbHelper.getReadableDatabase();
courseItems = new ArrayList<String>();
int layout = (Build.VERSION.SDK_INT >= 11) ? android.R.layout.simple_list_item_activated_1
: android.R.layout.simple_list_item_1;
adapter = new ArrayAdapter<String>(getActivity(), layout, courseItems);
// TODO: replace with a real list adapter.
setListAdapter(adapter);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState
.getInt(STATE_ACTIVATED_POSITION));
}
}
#Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
String[] projection = { DbHelper.COURSE_NAME };
Cursor c = db.query(DbHelper.TABLE_NAME, projection, null, null, null,
null, null);
c.moveToFirst();
while (c.moveToNext()) {
courseName = c.getString(c.getColumnIndex(DbHelper.COURSE_NAME));
courseItems.add(courseName);
}
c.close();
adapter.notifyDataSetChanged();
}
public void addCourse() {
String[] projection = { DbHelper.COURSE_NAME };
Cursor c = db.query(DbHelper.TABLE_NAME, projection, null, null, null,
null, null);
c.moveToFirst();
while (c.moveToNext()) {
courseName = c.getString(c.getColumnIndex(DbHelper.COURSE_NAME));
courseItems.add(courseName);
}
c.close();
adapter.notifyDataSetChanged();
bool = true;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException(
"Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
#Override
public void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(null);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(
activateOnItemClick ? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
public void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}

Having trouble with Custom Support Loader

I am setting up to use the Loader pattern and had issues using the cursor approach, so I have refactored my code because my tables do not use _id as the primary key because of the use of association tables and I setup my code to use the same basic structure as the LoaderCustomSupport.java example from the android developer site. All of the code works without errors and I can see that I have the proper data back and ready for the ListFragment to display but after the onLoadFinished call back completes the setData on the adapter the getView is never called. My getView looks like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
PhoneNumberListHolder holder;
if (row == null) {
row = mInflater.inflate(R.layout.phonenumber_row, parent, false);
holder=new PhoneNumberListHolder(row);
row.setTag(holder);
} else {
holder = (PhoneNumberListHolder)row.getTag();
}
holder.populateForm(this.phoneNumbers.get(position));
return row;
}
I am trying to use the holder pattern, but I am thinking that maybe it is part of my issue. Any ideas where I might be going wrong?
Here is the loader code (Like I said I followed the Google example for my first run changing what I thought I would need)
The Abstract Loader for my Class
/*
* Custom version of CommonsWare, LLC, AbstractCursorLoader
*
*/
package myApp.service.data;
import java.util.List;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
abstract public class AbstractPhoneNumberLoader extends AsyncTaskLoader<List<PhoneNumber>> {
abstract protected List<PhoneNumber> buildPhoneNumber();
List<PhoneNumber> lastPhoneNumber=null;
public AbstractPhoneNumberLoader(Context context) {
super(context);
}
#Override
public List<PhoneNumber> loadInBackground() {
List<PhoneNumber> data=buildPhoneNumber();
if (data!=null) {
// Make sure we fill the person
data.size();
}
return (data);
}
/**
* This will run on the UI thread, routing the results from the
* background to the consumer of the Person object
* (e.g., a PhoneNumberListAdapter).
*/
#Override
public void deliverResult(List<PhoneNumber> data) {
if (isReset()) {
// An async query attempted a call while the loader is stopped
if (data!=null) {
data.clear();
data=null;
//not sure the best option here since we cannot close the List object
}
return;
}
List<PhoneNumber> oldPhoneNumber=lastPhoneNumber;
lastPhoneNumber=data;
if (isStarted()) {
super.deliverResult(data);
}
if (oldPhoneNumber!=null && oldPhoneNumber!=data && oldPhoneNumber.isEmpty()) {
oldPhoneNumber.clear();
oldPhoneNumber=null;
}
}
/**
* Start an asynchronous load of the requested data.
* When the result is ready the callbacks will be called
* on the UI thread. If a previous load has completed
* and is still valid the result may be passed back to the
* caller immediately.
*
* Note: Must be called from the UI thread
*/
#Override
protected void onStartLoading() {
if (lastPhoneNumber!=null) {
deliverResult(lastPhoneNumber);
}
if (takeContentChanged() || lastPhoneNumber==null) {
forceLoad();
}
}
/**
* Must be called from the UI thread, triggered by
* a call to stopLoading().
*/
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task
cancelLoad();
}
/**
* Must be called from the UI thread, triggered by a
* call to cancel(). Here, we make sure our Person
* is null, if it still exists and is not already empty.
*/
#Override
public void onCanceled(List<PhoneNumber> data) {
if (data!=null && !data.isEmpty()) {
data.clear();
}
}
/**
* Must be called from the UI thread, triggered by a
* call to reset(). Here, we make sure our Person
* is empty, if it still exists and is not already empty.
*/
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (lastPhoneNumber!=null && !lastPhoneNumber.isEmpty()) {
lastPhoneNumber.clear();
}
lastPhoneNumber=null;
}
}
The Data Loader
/*
* Custom version of CommonsWare, LLC, SQLiteCursorLoader
*
*/
package myApp.service.data;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.List;
import myApp.service.data.ActorDbAdapter;
import android.content.Context;
public class PhoneNumberDataLoader extends AbstractPhoneNumberLoader {
ActorDbAdapter db=null;
protected final String actorId;
protected final String _PHONENUMBERID = "PhoneNumberId";
protected SimpleDateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy");
/**
* Constructor - takes the context to allow the database to be
* opened/created
*
* #param ctx the Context within which to work
*/
public PhoneNumberDataLoader(Context ctx, String actorId) {
super(ctx);
this.actorId = actorId;
getHelper(ctx);
}
// Get a database connection
private void getHelper(Context ctx) {
if (db==null) {
db=new ActorDbAdapter(ctx);
}
db.open();
}
// Loader Methods
/**
* Runs on a worker thread and performs the actual
* database query to retrieve the PhoneNumber List.
*/
#Override
protected List<PhoneNumber> buildPhoneNumber() {
return(db.readPhoneById(actorId));
}
/**
* Writes a semi-user-readable roster of contents to
* supplied output.
*/
#Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
writer.print(prefix);
writer.print("actorId=");
writer.println(actorId);
}
public void insert(PhoneNumber data, String actorId) {
new InsertTask(this).execute(db, data, actorId);
}
// Saved for Later, get Reads and Writes working first
// public void update(PhoneNumber data, String actorId, String whereClause, String[] whereArgs) {
// new UpdateTask(this).execute(db, data, actorId, whereClause, whereArgs);
// }
//
// public void delete(String actorId, String phoneNumberId, String whereClause, String[] whereArgs) {
// new DeleteTask(this).execute(db, actorId, phoneNumberId, whereClause, whereArgs);
// }
public void execSQL(String actorId) {
new ExecSQLTask(this).execute(db, actorId);
}
private class InsertTask extends ContentChangingTask<Object, Void, Void> {
InsertTask(PhoneNumberDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(Object... params) {
ActorDbAdapter db=(ActorDbAdapter)params[0];
PhoneNumber data=(PhoneNumber)params[1];
int actorId=Integer.parseInt((String)params[2]);
db.createPhoneNumber(data, actorId);
return(null);
}
}
// Saved for Later, get Reads and Writes working first
// private class UpdateTask extends
// ContentChangingTask<Object, Void, Void> {
// UpdateTask(PhoneNumberDataLoader loader) {
// super(loader);
// }
//
// #Override
// protected Void doInBackground(Object... params) {
// ActorDbAdapter db=(ActorDbAdapter)params[0];
// String table=(String)params[1];
// int actorId=Integer.parseInt((String)params[2]);
// String where=(String)params[3];
// String[] whereParams=(String[])params[4];
//
// db.updatePhoneNumber(table, values, where, whereParams);
//
// return(null);
// }
// }
//
// private class DeleteTask extends
// ContentChangingTask<Object, Void, Void> {
// DeleteTask(PhoneNumberDataLoader loader) {
// super(loader);
// }
//
// #Override
// protected Void doInBackground(Object... params) {
// ActorDbAdapter db=(ActorDbAdapter)params[0];
// int actorId=Integer.parseInt((String)params[1]);
// int phoneNumberId=Integer.parseInt((String)params[2]);
// String where=(String)params[3];
// String[] whereParams=(String[])params[3];
//
// db.deletePhoneNumber(table, where, whereParams);
//
// return(null);
// }
// }
private class ExecSQLTask extends
ContentChangingTask<Object, Void, Void> {
ExecSQLTask(PhoneNumberDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(Object... params) {
ActorDbAdapter db=(ActorDbAdapter)params[0];
String actorId=(String)params[1];
db.readPhoneById(actorId);
return(null);
}
}
}
Here is my full ListAdapter
package myApp.planner.utilities;
import java.util.ArrayList;
import java.util.List;
import myApp.planner.R;
import myApp.planner.codes.PhoneOrAddressTypeCode;
import myApp.service.data.PhoneNumber;
import myApp.service.data.PhoneNumberListData;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
public class PhoneNumberListAdapter extends ArrayAdapter<PhoneNumber> {
private List<PhoneNumber> phoneNumbers;
private final LayoutInflater mInflater;
private Activity activity;
public PhoneNumberListAdapter(Activity a, int textViewResourceId) {
super(a, textViewResourceId);
activity = a;
mInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setData(List<PhoneNumber> data) {
if (this.phoneNumbers==null) {
this.phoneNumbers = new ArrayList<PhoneNumber>();
}
this.phoneNumbers.clear();
if (data != null) {
for (PhoneNumber phoneNumber : data) {
this.phoneNumbers.add(phoneNumber);
}
}
}
public static class PhoneNumberListHolder {
private TextView actorid=null;
private TextView phonenumberid=null;
private TextView phonetype=null;
private TextView phonenumber=null;
private CheckBox isprimary=null;
PhoneNumberListHolder(View row) {
actorid=(TextView)row.findViewById(R.id.actorid);
phonenumberid=(TextView)row.findViewById(R.id.phonenumberid);
phonetype=(TextView)row.findViewById(R.id.txtphonetype);
phonenumber=(TextView)row.findViewById(R.id.txtphonenumber);
isprimary=(CheckBox)row.findViewById(R.id.isprimary);
}
//void populateForm(ArrayList<PhoneNumberListData> c, int position) {
void populateForm(PhoneNumber data) {
//PhoneNumberListData data = c.get(position);
// Attempt to add the Actor ID
if (actorid != null){
actorid.setText(data.getActor().get(0).getActorId()==0 ? "0": Integer.toString(data.getActor().get(0).getActorId()));
}
// Attempt to add the Phone Number Item ID
if (phonenumberid != null){
phonenumberid.setText(data.getPhoneNumberId()==0 ? "0": Integer.toString(data.getPhoneNumberId()));
}
// Attempt to add the Phone Number Type
if (phonetype != null){
phonetype.setText(data.getPhoneType()==null ? "": PhoneOrAddressTypeCode.valueOf(data.getPhoneType()).toString());
}
// Attempt to add the Phone Number
if (phonenumber != null){
phonenumber.setText(data.getPhoneNumber1()==null ? "": data.getPhoneNumber1());
}
// Attempt to add the is Primary Flag
if (isprimary != null){
isprimary.setChecked(data.getIsPrimary()==0 ? Boolean.FALSE: Boolean.TRUE);
}
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
PhoneNumberListHolder holder;
if (row == null) {
row = mInflater.inflate(R.layout.phonenumber_row, parent, false);
holder=new PhoneNumberListHolder(row);
row.setTag(holder);
} else {
holder = (PhoneNumberListHolder)row.getTag();
}
holder.populateForm(this.phoneNumbers.get(position));
return row;
}
}
The ListFragment:
package myApp.planner;
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SearchViewCompat;
import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
import android.text.TextUtils;
import android.content.Intent;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.view.ContextMenu;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import myApp.planner.R;
import myApp.planner.utilities.PhoneNumberListAdapter;
import myApp.service.data.PhoneNumber;
import myApp.service.data.PhoneNumberDataLoader;
public class ActorPhoneNumberListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<PhoneNumber>> {
public final static String ID_EXTRA="myapp.planner.actorid";
protected final static String TAG = "ActorPhoneNumberListFragment";
private static final int ADD_ID=Menu.FIRST + 1;
private static final int DELETE_ID=Menu.FIRST + 3;
private PhoneNumberListAdapter mAdapter=null;
private PhoneNumberDataLoader loader=null;
private String mCurFilter;
private String actorId = "0";
//private SharedPreferences prefs=null;
OnActorPhoneNumberListListener listener=null;
OnQueryTextListenerCompat mOnQueryTextListenerCompat;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.actorId = getActivity().getIntent().getExtras().getString(ID_EXTRA).toString();
}
#Override
public void onResume() {
super.onResume();
Bundle args=getArguments();
if (args!=null) {
loadPhoneNumbers(args.getString(ID_EXTRA));
}
// init Empty Test for no Phone numbers Found
// Add the menu options that we need to manage the list
setHasOptionsMenu(true);
// Hookup the dbAdapter and create a blank adapter
initList();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onListItemClick(ListView list, View view, int position, long id) {
if (listener!=null) {
//We will actually want the PhoneNumber Id here for the popup edit screen
String mId = actorId;
listener.onActorPhoneNumberListSelected(mId);
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.phonenumber_opton, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.addNewPhone) {
//add();
return(true);
} else if (item.getItemId()==R.id.help) {
startActivity(new Intent(getActivity(), HelpPage.class));
return(true);
} else if (item.getItemId()==R.id.phoneRefresh) {
//startActivity(new Intent(getActivity(), ActorPhoneNumberListFragment.class));
//We may just need to refresh the loader
return(true);
} else
return(super.onOptionsItemSelected(item));
}
public void setOnActorPhoneNumberListListener(OnActorPhoneNumberListListener listener) {
this.listener=listener;
}
public void loadPhoneNumbers(String actorId) {
this.actorId=actorId;
}
private void initList() {
mAdapter=new PhoneNumberListAdapter(getActivity(), R.layout.phonenumber_row);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
getActivity().getSupportLoaderManager().initLoader(0, null, this);
}
public interface OnActorPhoneNumberListListener {
void onActorPhoneNumberListSelected(String actorId);
}
#Override
public Loader<List<PhoneNumber>> onCreateLoader(int loaderId, Bundle args) {
loader= new PhoneNumberDataLoader(getActivity(), actorId);
return(loader);
}
#Override
public void onLoadFinished(Loader<List<PhoneNumber>> loader, List<PhoneNumber> data) {
// Now give the data to the adapter
mAdapter.setData(data);
mAdapter.notifyDataSetChanged();
//setListAdapter(mAdapter);
// Show the list
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
#Override
public void onLoaderReset(Loader<List<PhoneNumber>> arg0) {
// TODO Auto-generated method stub
mAdapter.setData(null);
}
}

Categories

Resources