Understanding FragmentStatePagerAdapter - android-fragments

I found this code online and am trying to test it out in my project. My project uses a database and I want to swipe between each record so I think ViewPager is the way to go. I have my activity and fragments already working but I have no clue how to implement the attached code into my project. What I'm looking for is where and how do I use this? From the activity or the fragment? and how do I go about doing it. I already have a cursor and the projection but now really sure how the two work together. I hope I'm making sense.
public class CursorPagerAdapter<F extends Fragment> extends FragmentStatePagerAdapter {
private final Class<F> fragmentClass;
private final String[] projection;
private Cursor cursor;
public CursorPagerAdapter(FragmentManager fm, Class<F> fragmentClass, String[] projection, Cursor cursor) {
super(fm);
this.fragmentClass = fragmentClass;
this.projection = projection;
this.cursor = cursor;
}
#Override
public F getItem(int position) {
if (cursor == null) // shouldn't happen
return null;
cursor.moveToPosition(position);
F frag;
try {
frag = fragmentClass.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
Bundle args = new Bundle();
for (int i = 0; i < projection.length; ++i) {
args.putString(projection[i], cursor.getString(i));
}
frag.setArguments(args);
return frag;
}
#Override
public int getCount() {
if (cursor == null)
return 0;
else
return cursor.getCount();
}
public void swapCursor(Cursor c) {
if (cursor == c)
return;
this.cursor = c;
notifyDataSetChanged();
}
public Cursor getCursor() {
return cursor;
}
}

This is how you've to modify your code
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction().add(R.id.item_detail_container, fragment).commit();
ViewPager vpPager = (ViewPager) findViewById(R.id.pager);
CursorPagerAdapter<ItemDetailFragment> adapterViewPager = new CursorPagerAdapter(
getSupportFragmentManager(), fragment_class, your_projection, your_cursor);
vpPager.setAdapter(adapterViewPager);

Related

Change button in listview with reference to data

i can speak english just little..
i made listview with sqlite db.
I want to implement this function
ex)
i have sqlite db (with listview. i made already. and listview have button)
rowId 1, 2, 3
number 0, 1, 0
i need like this
if ( number == 0) {
button.backgroundResource(R.drawble.icon1);
} else if ( number == 1) {
button.backgroundResource(R.drawble.icon2);
}
Attached pictures for easier understanding.
enter image description here
and this is my listadapter
public class ListAdapter extends BaseAdapter implements View.OnClickListener {
public interface ListBtnClickListener {
void onListBtnClick(int position, View view);
}
public ListAdapter(Context mContext, ArrayList<SongList> mList, ListBtnClickListener clickListener) {
this.mContext = mContext;
this.mList = mList;
this.listBtnClickListener = clickListener;
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSelectedItemsIds = new SparseBooleanArray();
}
#Override
public int getCount() {
return mList.size();
}
#Override
public Object getItem(int position) {
return mList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
viewHolder = new ViewHolder();
view = layoutInflater.inflate(R.layout.list_item, null);
viewHolder.relativeLayout = (RelativeLayout) view.findViewById(R.id.listview_item);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
_url = (TextView) view.findViewById(R.id.song_url);
_name = (TextView) view.findViewById(R.id.song_name);
_time = (TextView) view.findViewById(R.id.song_time);
_img = (ImageView) view.findViewById(R.id.song_thumbnail);
favorite = (Button) view.findViewById(R.id.favorite);
Bitmap bitmap = BitmapFactory.decodeByteArray(mList.get(position).get_img(), 0, mList.get(position).get_img().length);
_img.setImageBitmap(bitmap);
final SongList listViewItem = mList.get(position);
if (mList != null) {
_url.setText(listViewItem.get_url());
_name.setText(listViewItem.get_name());
_time.setText(listViewItem.get_time());
}
final SongList songList = mList.get(position);
favorite.setTag(position);
favorite.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
if (this.listBtnClickListener != null) {
this.listBtnClickListener.onListBtnClick((int) view.getTag(), view);
}
}
public class ViewHolder {
private RelativeLayout relativeLayout = null;
}
}
I assume you have some method like SongList.getNumber(). You can change your code in if block like this:
if (mList != null) {
_url.setText(listViewItem.get_url());
_name.setText(listViewItem.get_name());
_time.setText(listViewItem.get_time());
// assuming you have getNumber() method
int number = listViewItem.getNumber();
// checking if number is equal to 0
if(number == 0){
favorite.backgroundResource(R.drawble.icon1);
} else{
favorite.backgroundResource(R.drawble.icon2);
}
}
Edit: If you are storing number variable for only changing the background of button, then you can just use position parameter provided in getView() method. All you have to do is check if position is even or odd and change the background of the button accordingly.

Observe LiveData from ListView current Item

Basically i want to retrieve a int(score) generated from the current ListViewItem and assign it back to concrete TextView in my ListView.I am using SharedViewModel with LiveData but when i observe nothing happens.I am using Nav Architecture Component with Single activity.I'll be glad if someone helps.Thank u , here's some code.
public class ListFrag extends Fragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getCurrentScore().observe(getViewLifecycleOwner(), new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer s) {
for (int i = 0; i < myListView.getAdapter().getCount(); i++) {
v = myListView.getAdapter().getView(i,null, myListView);
finalScore = v.findViewById(R.id.finalScoreView);
if (s != null) {
itemAdapter = new ItemAdapter(getActivity(),items,bushido,description,s,finalScore);
myListView.setAdapter(itemAdapter);
finalScore.setText(String.valueOf(s));
}
((BaseAdapter)myListView.getAdapter()).notifyDataSetChanged();
}
}
});
}
public class SharedViewModel extends ViewModel
{
private MutableLiveData<Integer> currentScore = new MutableLiveData<>();
public LiveData<Integer> getCurrentScore(){
return currentScore;
}
public void setCurrentScore(Integer finito) {
currentScore.setValue(finito);
}
}
public class ItemAdapter extends BaseAdapter {
LayoutInflater mInflater;
String[] items;
String[] bushido;
String[] description;
TextView finalscorre;
Integer scr;
public ItemAdapter(Context c,String[] i ,String [] p ,String[] d, Integer scc,TextView sc) {
items = i;
bushido = p;
description = d;
finalscorre = sc;
scr = scc;
mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int i) {
return items[i];
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View convertView, ViewGroup parent) {
View v = mInflater.inflate(R.layout.my_listview_detail, null);
TextView nameTextView = v.findViewById(R.id.NameTextView);
TextView bushidoTextView = v.findViewById(R.id.bushidoTextView);
TextView descriptionTextView = v.findViewById(R.id.descriptionTextView);
finalscorre = v.findViewById(R.id.finalScoreView);
String name = items[i];
String desc = description[i];
String bush = bushido[i];
finalscorre.setText("Waat");
nameTextView.setText(name);
descriptionTextView.setText(desc);
bushidoTextView.setText(bush);
ItemAdapter.this.notifyDataSetChanged();
return v;
}
}
When i try to assign the LiveData in TextView out of the ListView it works.But when i try this ,nothings happen (no errors and no result).
Adapters act as a bridge between the data (in your case, the string array you pass into the adapter), and the ListView (in your case, myListView). Any change to the ListView needs to be follow these steps:
make desired changes to the data itself
pass this new data to the adapter
adapter updates the list view
I have wrote some example code:
ItemAdapter
public class ItemAdapter extends BaseAdapter {
LayoutInflater mInflater;
String[] items;
String[] bushido;
String[] description;
// TextView finalscorre; // I commented out this TextView please see the comment below
Integer scr;
public ItemAdapter(Context c,String[] i ,String [] p ,String[] d, Integer scc,TextView sc) {
items = i;
bushido = p;
description = d;
// finalscorre = sc;
scr = scc;
mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void updateItems(String[] i, String[] p, String[] d, Integer scc) {
items = i;
bushido = p;
description = d;
scr = scc;
// notify the adapter to refresh the list view.
notifyDataSetChanged()
}
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int i) {
return items[i];
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View convertView, ViewGroup parent) {
View v = mInflater.inflate(R.layout.my_listview_detail, null);
TextView nameTextView = v.findViewById(R.id.NameTextView);
TextView bushidoTextView = v.findViewById(R.id.bushidoTextView);
TextView descriptionTextView = v.findViewById(R.id.descriptionTextView);
//finalscorre = v.findViewById(R.id.finalScoreView);
TextView finalscorre = v.findViewById(R.id.finalScoreView);
String name = items[i];
String desc = description[i];
String bush = bushido[i];
// finalscorre.setText("Waat");
finalscorre.setText(scr);
nameTextView.setText(name);
descriptionTextView.setText(desc);
bushidoTextView.setText(bush);
// ItemAdapter.this.notifyDataSetChanged(); Do NOT call this method inside getView
return v;
}
}
Fragment
public class ListFrag extends Fragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Create and set adapter just once. Do not create or set new adapter in observer, for loop, etc.
itemAdapter = new ItemAdapter(getActivity(),items,bushido,description,s,finalScore);
myListView.setAdapter(itemAdapter);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getCurrentScore().observe(getViewLifecycleOwner(), new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer s) {
itemAdapter.updateItems(items,bushido,description,s);
}
});
}
}
I wasn't able to figure out what finalscorre supposed to be so I assumed that this is the text view that stores the final score that you mentioned, and all list view items should have the same value. If this is not the case please clarify in your question.
Also note that while this solution is enough to solve the specific problem you mentioned, their are some other improvements that can be made:
Use RecyclerView instead of ListView.
Instead of maintaining multiple String[], define a POJO that represent the item, and have a single array.
Also, checking this adapter implementation in google sample will help.
inside adapter you are doing nothing that will update your LiveData

android fragment reloading (onCreate) each time when back Button pressed

I am new in android using fragments in my Project. first time my fragment is creating then api called and get data load in fragment. here when i clicked at any item i replaced fragment by another fragment there also another api called and load data to fragment.
now here problem situation generated for me.
from here i back Button pressed.
fragment reloading same as first time creating but it should be show data as i left before going to next fragment.
so please provide me solution how i can get same data as i left means savedInstanceState data.
im my first fragment getCategory method call Api and get Data first time when i choose any category i replace fragment with another fragment but when i m returning same getCategory method recall perform same process as it first time.
fragment should not call api method again on backpressed it should show same category on this i clicked before.
my first fragment where calling api......
public class LandingFragment 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 GridLayoutManager gridLayoutManager;
private static RecyclerView category_Grid;
private Fragment myFragment = null;
ProgressBar mProgressView;
View mLoginFormView;
private Category category;
private CategoryAdapter categoryAdapter;
private List<CategoryObject> rowListItem;
private String productId;
private OnFragmentInteractionListener mListener;
public LandingFragment() {
// 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 LandingFragment.
*/
// TODO: Rename and change types and number of parameters
public static LandingFragment newInstance(String param1, String param2) {
LandingFragment fragment = new LandingFragment();
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);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v= inflater.inflate(R.layout.fragment_landing, container, false);
return v;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initViews(view);
RecyclerViewListeners();
}
// 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(Activity 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);
}
private void initViews(final View v) {
mLoginFormView = (View)v.findViewById(R.id.mainView);
mProgressView = (ProgressBar)v.findViewById(R.id.login_progress);
category_Grid = (RecyclerView)v.findViewById(R.id.cat_grid);
category_Grid.setHasFixedSize(true);
gridLayoutManager = new GridLayoutManager(getActivity(), 3);
category_Grid.setLayoutManager(gridLayoutManager);
}
private void RecyclerViewListeners(){
category_Grid.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), category_Grid, new ItemClickListener(){
#Override
public void onClick(View view, int position) {
String entityId = rowListItem.get(position).getCategoryId();
String catName = rowListItem.get(position).getName();
Integer ishave = rowListItem.get(position).getIshaveSubcategories();
if(ishave==1) {
myFragment = SubcategoryFragment.newInstance(""+catName, "" + entityId);
ActivityUtils.launchFragementWithAnimation(myFragment, getActivity());
}else{
myFragment = ProductListFragment.newInstance("", "" + entityId);
ActivityUtils.launchFragementWithAnimation(myFragment, getActivity());
}
}
#Override
public void onLongClick(View view, int position) {
}
}));
}
public void getCategory() {
showProgress(true);
String URL = getResources().getString(R.string.category_api);
StringRequest req = new StringRequest(Request.Method.POST,URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
VolleyLog.v("Response:%n %s", response);
Gson gson = new GsonBuilder().serializeNulls().create();
try {
JSONObject jsonObject = new JSONObject(response);
if (jsonObject.getString("status").equals(getResources().getString(R.string.response_success))){
category = gson.fromJson(response, Category.class);
rowListItem = category.getCategory();
if(navigationUpdated){
someEventListener.someEvent(rowListItem);
navigationUpdated = false;
}
Log.d("CATEGORYID::::::::",""+rowListItem.get(1).getCategoryId());
categoryAdapter = new CategoryAdapter(getActivity(),rowListItem);
category_Grid.setAdapter(categoryAdapter);
categoryAdapter.notifyDataSetChanged();
return;
}
else if (jsonObject.getString("status").equals(getResources().getString(R.string.login_Er_respose))){
Log.e("","ERRORRRRRR");
return;
}
} catch (JSONException e) {
showProgress(false);
Log.e("My App", "Could not parse malformed JSON: \"" + response + "\"");
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
showProgress(false);
VolleyLog.e("Error: ", error.getMessage());
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
params.put("Content-Type","application/x-www-form-urlencoded");
return params;
}
};
AppController.getInstance().addToRequestQueue(req);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
private void showProgress(final boolean show) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
mLoginFormView.animate().setDuration(shortAnimTime).alpha(
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
});
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mProgressView.animate().setDuration(shortAnimTime).alpha(
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
}
});
} else {
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
}
You can check your rowListItem.size(), if it's size is 0 then call getCategory() service, otherwise load your data from your rowListItem. Here is sample code which I am using to load data from arraylist if it is not empty:
if (mArrayArticle.size() == 0) {
isDataLoading = true;
mRecyclerList.setVisibility(View.INVISIBLE);
getCategory();
} else {
mHomeItemAdapter = new HomeItemAdapter(getActivity(), mArrayArticle, this);
mRecyclerList.setAdapter(mHomeItemAdapter);
}
Here mArrayArticle is my ArrayList, Hope it will help you.
for more clarification i want to tell..
how i implement the #Bhvk_AndroidBee solution
fragment backpressed call onActivityCreated Method so first overridethis method in fragment
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//here you can check null condition for rowListItem
}
}
inside onActivityCreated method I checked the condition like that
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(rowListItem!=null){
categoryAdapter = new CategoryAdapter(getActivity(),rowListItem);
category_Grid.setAdapter(categoryAdapter);
categoryAdapter.notifyDataSetChanged();
}else {
//call the method for first time creating your view
getCategory();
}
}
hope this would be helpfull for more strugglers like me...

ListView/adapter throwing IndexOutOfBound

I have a listview with a getCount() of 7. I want all 7 items to be shown regardless if any data from my database is available to populate them. If no data is available then an item should just be blank with predetermined text.
When I have not hardcoded 7 database entries beforehand to go into the 7 views then I get an indexoutofbound exception when running the app due to the 7 items not being able to be populated accordingly. This happens in ListMealsAdapter.java when method Meal currentItem = getItem(position); is called and triggers public Meal getItem(int position).
I am looking for a condition statement that I can use for my listview/adapter that can handle an empty database so that the index does not go out of bounds. Also, is the BaseAdapter suited for what I want to do?
MainActivity.java
public class MainActivity extends BaseActivity {
public static final String TAG = "MainActivity";
private ListView mListviewMeals;
private MealDAO mMealDao;
private List<Meal> mListMeals;
private ListMealsAdapter mAdapter;
private SQLiteDatabase mDatabase;
DatabaseHelper mDbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activateToolbar(1);
// initialize views
initViews();
// fill the dailyListView
mMealDao = new MealDAO(this);
mListMeals = mMealDao.getAllMeals();
mAdapter = new ListMealsAdapter(this, mListMeals, MainActivity.this);
mListviewMeals.setAdapter(mAdapter);
}
private void initViews() {
this.mListviewMeals = (ListView) findViewById(R.id.view_daily_list);
}
ListMealsAdapter.java
public class ListMealsAdapter extends BaseAdapter {
public static final String TAG = "ListMealsAdapter";
Activity mActivity;
private List<Meal> mItems;
private LayoutInflater mInflater;
public ListMealsAdapter(Context context, List<Meal> listMeals, Activity activity) {
super();
mActivity = activity;
this.setItems(listMeals);
this.mInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return 7;
}
#Override
public Meal getItem(int position) {
return (getItems() != null && !getItems().isEmpty()) ? getItems().get(position) : null;
}
#Override
public long getItemId(int position) {
return (getItems() != null && !getItems().isEmpty()) ? getItems().get(position).getId() : position;
}
#Override
public View getView(int position, final View convertView, final ViewGroup parent) {
View v = convertView;
final ViewHolder holder;
if (v == null) {
v = mInflater.inflate(R.layout.list_item_daily, parent, false);
holder = new ViewHolder();
holder.txtDescription = (TextView) v.findViewById(R.id.txtBreakfast);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
// fill row data
Meal currentItem = getItem(position);
if (currentItem != null) {
holder.txtDescription.setText(currentItem.getDescription());
}
return v;
}
public List<Meal> getItems() {
return mItems;
}
public void setItems(List<Meal> mItems) {
this.mItems = mItems;
}
class ViewHolder {
TextView txtDescription;
}
}
Meal.java
public class Meal implements Serializable {
public static final String TAG = "Meal";
private static final long serialVersionUID = -7406082437623008161L;
private long mId;
private int mType;
private String mDescription;
public Meal() {
}
public Meal(int type, String description) {
this.mType = type;
this.mDescription = description;
}
public long getId() {
return mId;
}
public void setId(long mId) {
this.mId = mId;
}
public int getType() {
return mType;
}
public void setType(int mType) {
this.mType = mType;
}
public String getDescription() {
return mDescription;
}
public void setDescription(String mDescription) {
this.mDescription = mDescription;
}
}
MealDAO.java
public class MealDAO {
public static final String TAG = "MealDAO";
private SQLiteDatabase mDatabase;
private DatabaseHelper mDbHelper;
private Context mContext;
private String[] mAllColumns = { DatabaseHelper.COLUMN_MEAL_ID,
DatabaseHelper.COLUMN_MEAL_TYPE, DatabaseHelper.COLUMN_MEAL_DESCRIPTION};
public MealDAO(Context context) {
this.mContext = context;
mDbHelper = new DatabaseHelper(context);
// open the database
try {
open();
} catch (SQLException e) {
Log.e(TAG, "SQLException on opening database " + e.getMessage());
e.printStackTrace();
}
}
public void open() throws SQLException {
mDatabase = mDbHelper.getWritableDatabase();
}
public void close() {
mDbHelper.close();
}
public List<Meal> getAllMeals() {
List<Meal> listMeals = new ArrayList<Meal>();
Cursor query = mDatabase.rawQuery("SELECT * from meal", null);
if(query.moveToFirst()) {
do {
// Cycle through all records
Meal meal = cursorToMeal(query);
listMeals.add(meal);
} while(query.moveToNext());
}
return listMeals;
}
public Meal getMealById(long id) {
Cursor cursor = mDatabase.query(DatabaseHelper.TABLE_MEALS, mAllColumns,
DatabaseHelper.COLUMN_MEAL_ID + " = ?",
new String[] { String.valueOf(id) }, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
Meal meal = cursorToMeal(cursor);
return meal;
}
protected Meal cursorToMeal(Cursor cursor) {
Meal meal = new Meal();
meal.setId(cursor.getLong(0));
meal.setType(cursor.getInt(1));
meal.setDescription(cursor.getString(2));
return meal;
}
}
After a LOT of trial and error I finally found an acceptable solution to my problem. What I did was to add a default row to my database for the view items that I wanted to have a predetermined database entry when no data had been entered beforehand.
I then made sure to start at index 2, making sure that index 1 would be reserved for my default value. If the index comes out of bounds then the exception is caught and the default database entry will be added to the array.
public Meal getItem(int position) {
Meal result;
try {
result = (getItems() != null && !getItems().isEmpty()) ? getItems().get(position) : null;
} catch (Exception e) {
Meal default = getItem(0);
return default;
}
return result;
}
Meal currentItem = getItem(position + 1);
if (currentItem != null) {
holder.txtDescription.setText(currentItem.getDescription());
}
With that change things have been running smooth ever since. I hope this can help someone else as well.

how to get the data and update to UI when new record available in SqliteDB?

I am working on a sample application by communicate with .net web service.In my application I am getting records from web service into my activity class then i am displaying entire records in ListView by using ArrayAdapter and also i am running a service class at background process for get the latest record from web service when the new records are available from web service then i am saving those records in to SQLite data base.This process is happening at back ground.Here i would like to get the latest data from SQLite DB and append to my ListView.
I have implemented Activity class as follows:
public class GetMsgsScreen extends ListActivity
{
private LayoutInflater mInflater;
private Vector<RowData> data;
RowData rd;
static String[] userName = null;
static String[] usrMessages = null;
private Integer[] imgid = null;
ShoutRepeatService bg;
////////////////////////////////////////////////////
List<Message> resultShoutMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
resultMessage = new ParseXml().convertMessages(new Model().getMessages("0"));
usrMessages = new String[resultMessage.size()];
userName = new String[resultMessage.size()];
imgid = new Integer[resultMessage.size()];
getSharedPreferences("Values", 0).edit().putString("msgid",resultMessage.get(0).getMessageID()).commit();
for(int i=0;i<resultMessage.size();i++)
{
Log.v("GetMsgsScreen", "resultMessage*******>>>>"+resultMessage.get(i).getMessageText());
Log.v("GetMsgsScreen", "resultNames*******>>>>"+resultMessage.get(i).getUserFirstName());
usrMessages[i] = resultMessage.get(i).getMessageText();
userName[i] = resultMessage.get(i).getUserFirstName();
imgid[i] = R.drawable.person;
}
///////////////////////////////////////////////////////
mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
data = new Vector<RowData>();
for(int i=0;i<userName.length;i++){
try {
rd = new RowData(i,userName[i],usrMessages[i]);
} catch (ParseException e) {
e.printStackTrace();
}
data.add(rd);
}
CustomAdapter adapter = new CustomAdapter(this, R.layout.list, R.id.usrName, data);
setListAdapter(adapter);
bindService(new Intent(GetMsgsScreen.this, RepeatService.class), mConnection, Context.BIND_AUTO_CREATE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getListView().setTextFilterEnabled(true);
}
#Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
bg = ((RepeatService.MyBinder) binder).getService();
Toast.makeText(GetMsgsScreen.this, "Connected",
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
bg = null;
}
};
public void onListItemClick(ListView parent, View v, int position, long id) {
Toast.makeText(getApplicationContext(), "You have selected "
+(position+1)+"th item", Toast.LENGTH_SHORT).show();
}
private class CustomAdapter extends ArrayAdapter<RowData> {
public CustomAdapter(Context context, int resource, int textViewResourceId, List<RowData> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
TextView name = null;
TextView messages = null;
ImageView i11=null;
RowData rowData= getItem(position);
if(null == convertView){
convertView = mInflater.inflate(R.layout.list, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
name = holder.gettitle();
name.setText(rowData.mName);
messages = holder.getdetail();
messages.setText(rowData.mMessage);
i11=holder.getImage();
i11.setImageResource(imgid[rowData.mId]);
return convertView;
}
private class ViewHolder {
private View mRow;
private TextView names = null;
private TextView messageText = null;
private ImageView i11=null;
public ViewHolder(View row) {
mRow = row;
}
public TextView gettitle() {
if(null == names){
names = (TextView) mRow.findViewById(R.id.usrName);
}
return names;
}
public TextView getdetail() {
if(null == messageText){
messageText = (TextView) mRow.findViewById(R.id.msgText);
}
return messageText;
}
public ImageView getImage() {
if(null == i11){
i11 = (ImageView) mRow.findViewById(R.id.img);
}
return i11;
}
}
}
}
I have implemented background service class as follows:
public class RepeatService extends Service
{
List<Message> resultMessage;
String[] userNameLatest = null;
String[] usrMessagesLatest = null;
String[] usrMessageID = null;
String msgID = null;
private Timer timer = new Timer();
private static final long UPDATE_INTERVAL = 500;
SQLiteDB db;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
pollForUpdates();
super.onCreate();
}
private void pollForUpdates() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Log.v("!!!!!!!!!!!!!!!!", "service is calling");
msgID = getSharedPreferences("Values", 0).getString("msgid","");
resultMessage = new ParseXml().convertMessages(new Model().getMessages(msgID));
usrMessagesLatest = new String[resultMessage.size()];
userNameLatest = new String[resultMessage.size()];
usrMessageID = new String[resultMessage.size()];
db = new SQLiteDB();
for(int i=0;i<resultMessage.size();i++)
{
Log.v("RepeatService", "getMessageID------>"+resultMessage.get(i).getMessageID());
Log.v("RepeatService", "getMessageText------>"+resultMessage.get(i).getMessageText());
Log.v("RepeatService", "getUserFirstName------>"+resultMessage.get(i).getUserFirstName());
usrMessagesLatest[i] = resultMessage.get(i).getMessageText();
userNameLatest[i] = resultMessage.get(i).getUserFirstName();
usrMessageID[i] = resultMessage.get(i).getMessageID();
//Save the data into Sqlite db here
db.insertValues(usrMessageID[i], userNameLatest[i], usrMessagesLatest[i], RepeatService.this);
}
}
}, 0, UPDATE_INTERVAL);
Log.v(getClass().getSimpleName(), "Timer started.");
}
public class MyBinder extends Binder {
ShoutRepeatService getService()
{
return ShoutRepeatService.this;
}
}
}
The above class always run at back ground if any new record available from web service then store the record into Sqlite db.
From the above code i can save the data in to Sqlite data base then
How can i show the latest record to my ListView on My Activity class?
please any body help me with code explanation.........
I would probably use a BroadcastReceiver that is notified from the service when something new has been added. It could then update your list. Also look at LocalBroadcastManager since all the communication is in your app.

Resources