I'm querying the MediaStore, joining Images and Thumbnails, and loading in a GridView. This works fine enough, but I can't figure out how to update my app when a new photo appears in the MediaStore (typically when taken by the camera). The default gallery app automatically loads the new image, but my app does nothing. I've tried registering content observers, and I've even tried adding a manual "refresh" menu button, but the only way to load the new image is to stop and restart the entire app.
Edit
Actually, that's not entirely true. If I take a new photo, and switch to some other gallery app or widget, then this other app will load the new image (thumbnail) and my app will then suddenly also refresh. This indicates that I am observing some events, right, since the new thumbnail eventually appears automatically in my app? Maybe I'm just not observing the right ones. I just don't understand how the manual refresh accomplishes nothing.
I'm posting the relevant java files, maybe someone can see what I'm forgetting, or am doing wrong?
I'm at a loss, been working at this for quite some time, so please forgive me if the post is too vague. I'll try to add whatever details are missing.
PhotoFragment
package com.example.android.galleri.app;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.TextView;
import com.example.android.galleri.app.data.PhotoContract;
public class PhotoFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private final static int LOADER_ID = 87;
private PhotoAdapter mPhotoAdapter;
private int mPosition;
private GridView mGridView;
private TextView mEmptyView;
private int count_mem = -1;
private static final String SELECTED_KEY = "POSITION";
private boolean mTwoPane;
private boolean DF_hidden = false;
// these are the data we want from MediaStore
private final static String[] THUMBNAIL_COLUMNS = {
PhotoContract.ThumbEntry.COLUMN_THUMB_ID,
PhotoContract.ThumbEntry.COLUMN_DATA,
PhotoContract.ThumbEntry.COLUMN_IMAGE_ID,
PhotoContract.ThumbEntry.COLUMN_TITLE,
PhotoContract.ThumbEntry.COLUMN_DESC,
PhotoContract.ThumbEntry.COLUMN_DATE
};
static final int COL_THUMB_ID = 0;
static final int COL_THUMB_DATA = 1;
static final int COL_THUMB_IMAGE_ID = 2;
static final int COL_TITLE = 3;
static final int COL_DESC = 4;
static final int COL_DATE = 5;
public void setTwoPaneUI(boolean pTwoPane) {
mTwoPane = pTwoPane;
}
// interfaces
public interface Callback {
public void onItemSelected(Uri photoUri);
}
public interface FragmentCallback {
public void onTaskDone(int count);
}
public PhotoFragment() {
}
public int getPosition() {
return mPosition;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
getLoaderManager().initLoader(LOADER_ID, null, this);
super.onActivityCreated(savedInstanceState);
}
public void onNewCameraEvent() {
Log.v("JOAKIM", "PhotoFragment.onNewCameraEvent() triggering a refresh...");
restartLoader();
}
// https://stackoverflow.com/questions/22241705/calling-a-activity-method-from-broadcastreceiver-in-android
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// internet lost alert dialog method call from here...
Log.v("JOAKIM", "PhotoFragment.broadcastReceiver.onReceive() captured the image!");
onNewCameraEvent();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
getActivity().registerReceiver(broadcastReceiver, new IntentFilter("TRIGGER_A_REFRESH"));
}
#Override
public void onDestroy() {
super.onDestroy();
getActivity().unregisterReceiver(broadcastReceiver);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.photofragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
Log.v("JOAKIM", "PhotoFragment.onOptionsItemSelected() refresh clicked");
// https://stackoverflow.com/questions/15271271/android-callback-asynctask-to-fragmentnot-activity
ManualRefreshTask refreshTask = new ManualRefreshTask(
new FragmentCallback() {
#Override
public void onTaskDone(int count) {
// loader is restarted every time, since I couldn't
// get the logic to work 100%
restartLoader();
/*
// if the number of images has changed, restart loader
if (count != count_mem) restartLoader();
*/
count_mem = count;
}
});
refreshTask.execute(getActivity().getContentResolver());
return true;
}
return super.onOptionsItemSelected(item);
}
public void restartLoader() {
getLoaderManager().restartLoader(LOADER_ID, null, this);
}
#Override
public void onSaveInstanceState(Bundle outState) {
if (mPosition != GridView.INVALID_POSITION) {
outState.putInt(SELECTED_KEY, mPosition);
}
super.onSaveInstanceState(outState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mPhotoAdapter = new PhotoAdapter(getActivity(), null, 0);
GridView gridView = (GridView) rootView.findViewById(R.id.listview_photo);
gridView.setAdapter(mPhotoAdapter);
mEmptyView = (TextView) rootView.findViewById(R.id.list_empty);
mGridView = gridView;
// handle user clicking on an image
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Cursor cursor = (Cursor) parent.getItemAtPosition(position);
if (cursor != null) {
Uri baseUri = PhotoContract.PhotoEntry.buildPhotoUriWithId(cursor.getLong(COL_THUMB_IMAGE_ID));
Log.v("JOAKIM", "PhotoFragment.onItemClick() image_id = " + cursor.getLong(COL_THUMB_IMAGE_ID)
+ ", baseUri = " + baseUri.toString());
// make sure detail fragment is visible
if (mTwoPane) showDetailFragment();
else Utility.setPosition(position); // else (single-pane): store position clicked!
((Callback)getActivity()).onItemSelected(baseUri);
}
mPosition = position;
}
});
if (savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY)) {
mPosition = savedInstanceState.getInt(SELECTED_KEY);
}
return rootView;
}
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
Uri thumbs_uri = PhotoContract.ThumbEntry.CONTENT_URI;
return new CursorLoader(getActivity(), thumbs_uri, THUMBNAIL_COLUMNS,
null,null, // read everything (all thumbnails)
PhotoContract.ThumbEntry.COLUMN_THUMB_ID + " DESC");
}
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
if (cursor != null) {
// register observer onto cursor
cursor.setNotificationUri(getActivity().getContentResolver(), PhotoContract.ThumbEntry.CONTENT_URI);
mPhotoAdapter.swapCursor(cursor);
if (mPosition != GridView.INVALID_POSITION) {
mGridView.setSelection(mPosition); // scroll into view
}
}
// save (set) cursor in Utility
Utility.setCursor(cursor);
if (cursor == null) {
mEmptyView.setText("No Images on Device");
mEmptyView.setVisibility(View.VISIBLE);
if (mTwoPane) {
mGridView.setVisibility(View.GONE);
hideDetailFragment();
}
} else {
mEmptyView.setVisibility(View.GONE);
if (mTwoPane) {
mGridView.setVisibility(View.VISIBLE);
showDetailFragment();
}
}
}
public void hideDetailFragment() {
if (!DF_hidden) {
Log.v("JOAKIM", "PhotoFragment.onLoadFinished() remove detail framelayout");
FrameLayout container = (FrameLayout) getActivity().findViewById(R.id.photo_detail_container);
container.setVisibility(View.GONE);
DF_hidden = true;
Display display = ((WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
int numColumns = 10;
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) numColumns = 8;
else numColumns = 10;
mGridView.setNumColumns(numColumns);
}
}
public void showDetailFragment() {
if (DF_hidden) {
Log.v("JOAKIM", "PhotoFragment.onLoadFinished() show detail fragment");
FrameLayout container = (FrameLayout) getActivity().findViewById(R.id.photo_detail_container);
container.setVisibility(View.VISIBLE);
DF_hidden = false;
mGridView.setNumColumns(6);
}
}
#Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
mPhotoAdapter.swapCursor(null);
}
}
PhotoContract
package com.example.android.galleri.app.data;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.util.Log;
import java.util.HashMap;
import java.util.Map;
public class PhotoContract {
public static final String CONTENT_AUTHORITY = "com.example.android.galleri.app";
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
public static final String PATH_THUMBS = "thumbs";
public static final String PATH_PHOTO = "photo";
public static final String PATH_COMMENT = "comment";
//public static final String PATH_AUTHOR = "author";
// define updateable fields (where to update them)
public static final String TARGET_EXIF = "EXIF";
public static final String TARGET_MEDIASTORE = "MediaStore.Images.Media";
public static final String TARGET_MEDIASTORE_THUMBS = "MediaStore.Images.Thumbnails";
public static final class ThumbEntry {
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendPath(PATH_THUMBS).build();
public static final String COLUMN_THUMB_ID = MediaStore.Images.Thumbnails._ID;
public static final String COLUMN_DATA = MediaStore.Images.Thumbnails.DATA;
public static final String COLUMN_IMAGE_ID = MediaStore.Images.Thumbnails.IMAGE_ID;
public static final String COLUMN_IMAGE_PK = MediaStore.Images.Media._ID;
public static final String COLUMN_TITLE = MediaStore.Images.Media.TITLE;
public static final String COLUMN_DESC = MediaStore.Images.Media.DESCRIPTION;
public static final String COLUMN_DATE = MediaStore.Images.Media.DATE_TAKEN;
public static final String CONTENT_TYPE =
ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_THUMBS;
public static final Map<String, String> COL_TYPES;
static {
COL_TYPES = new HashMap<String, String>();
COL_TYPES.put(COLUMN_THUMB_ID, TARGET_MEDIASTORE_THUMBS);
COL_TYPES.put(COLUMN_DATA, TARGET_MEDIASTORE_THUMBS);
COL_TYPES.put(COLUMN_IMAGE_ID, TARGET_MEDIASTORE_THUMBS);
COL_TYPES.put(COLUMN_TITLE, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DESC, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DATE, TARGET_MEDIASTORE);
}
}
public static final class PhotoEntry {
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendPath(PATH_PHOTO).build();
public static final String COLUMN_IMAGE_ID = MediaStore.Images.Media._ID;
public static final String COLUMN_DISPLAY_NAME = MediaStore.Images.Media.DISPLAY_NAME;
public static final String COLUMN_DATA = MediaStore.Images.Media.DATA;
public static final String COLUMN_DESC = MediaStore.Images.Media.DESCRIPTION;
public static final String COLUMN_DATE_TAKEN = MediaStore.Images.Media.DATE_TAKEN;
public static final String COLUMN_DATE_ADDED = MediaStore.Images.Media.DATE_ADDED;
public static final String COLUMN_TITLE = MediaStore.Images.Media.TITLE;
public static final String COLUMN_SIZE = MediaStore.Images.Media.SIZE;
public static final String COLUMN_ORIENTATION = MediaStore.Images.Media.ORIENTATION;
public static final String COLUMN_HEIGHT = MediaStore.Images.Media.HEIGHT;
public static final String COLUMN_WIDTH = MediaStore.Images.Media.WIDTH;
public static final String COLUMN_EXIF_COMMENT = "UserComment";
public static final String COLUMN_EXIF_AUTHOR = "Author";
public static final Map<String, String> COL_TYPES;
static {
COL_TYPES = new HashMap<String, String>();
COL_TYPES.put(COLUMN_IMAGE_ID, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DISPLAY_NAME, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DATA, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DESC, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DATE_TAKEN, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_DATE_ADDED, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_TITLE, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_SIZE, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_ORIENTATION, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_HEIGHT, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_WIDTH, TARGET_MEDIASTORE);
COL_TYPES.put(COLUMN_EXIF_COMMENT, TARGET_EXIF);
COL_TYPES.put(COLUMN_EXIF_AUTHOR, TARGET_EXIF);
}
public static final String CONTENT_TYPE =
ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_PHOTO;
public static final String CONTENT_ITEM_TYPE =
ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_PHOTO;
// makes an URI to a specific image_id
public static final Uri buildPhotoUriWithId(Long photo_id) {
return CONTENT_URI.buildUpon().appendPath(Long.toString(photo_id)).build();
}
// since we will "redirect" the URI towards MediaStore, we need to be able to extract IMAGE_ID
public static Long getImageIdFromUri(Uri uri) {
return Long.parseLong(uri.getPathSegments().get(1)); // always in position 1
}
}
}
PhotoProvider
package com.example.android.galleri.app.data;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.AbstractWindowedCursor;
import android.database.Cursor;
import android.database.CursorJoiner;
import android.database.CursorWindow;
import android.database.CursorWrapper;
import android.database.MatrixCursor;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Map;
public class PhotoProvider extends ContentProvider {
// The URI Matcher used by this content provider.
private static final UriMatcher sUriMatcher = buildUriMatcher();
// query: get all thumbnails, or get specific image
static final int THUMBS = 100;
static final int PHOTO = 101;
static final int FIRST_PHOTO = 102;
// update: set comment etc
static final int PHOTO_COMMENT = 200;
static UriMatcher buildUriMatcher() {
// 1) The code passed into the constructor represents the code to return for the root
// URI. It's common to use NO_MATCH as the code for this case. Add the constructor below.
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = PhotoContract.CONTENT_AUTHORITY;
// 2) Use the addURI function to match each of the types. Use the constants from
// WeatherContract to help define the types to the UriMatcher.
// get all thumbnails (with a JOIN towards MediaStore.Images, to get title and description, too)
matcher.addURI(authority, PhotoContract.PATH_THUMBS, THUMBS);
// matches photo (no ID). Means get first image
matcher.addURI(authority, PhotoContract.PATH_PHOTO, FIRST_PHOTO);
// matches photo/<any number> meaning any photo ID
matcher.addURI(authority, PhotoContract.PATH_PHOTO + "/#", PHOTO);
// matches photo/<photo id>/comment/ (comment text in ContentValues)
matcher.addURI(authority, PhotoContract.PATH_PHOTO + "/#/" + PhotoContract.PATH_COMMENT, PHOTO_COMMENT);
// 3) Return the new matcher!
return matcher;
}
#Override
public String getType(Uri uri) {
// Use the Uri Matcher to determine what kind of URI this is.
final int match = sUriMatcher.match(uri);
// Note: We always return single row of data, so content-type is always "a dir"
switch (match) {
case PHOTO_COMMENT:
return PhotoContract.PhotoEntry.CONTENT_TYPE;
case PHOTO:
return PhotoContract.PhotoEntry.CONTENT_TYPE;
case THUMBS:
return PhotoContract.ThumbEntry.CONTENT_TYPE;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
#Override
public boolean onCreate() {
return true; // enough?
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// determine whether this is THUMBS or FULLSIZE query
int match = sUriMatcher.match(uri);
switch (match) {
case THUMBS: {
// split projection into MediaStore and MediaStore.Thumbs parts
ArrayList<String> MS_proj = new ArrayList<>();
ArrayList<String> MS_proj_thumbs = new ArrayList<>();
for (String f : projection) {
if (PhotoContract.ThumbEntry.COL_TYPES.get(f).equals(PhotoContract.TARGET_MEDIASTORE)) {
MS_proj.add(f);
} else {
MS_proj_thumbs.add(f);
}
}
String[] MS_proj_thumbs_array = new String[MS_proj_thumbs.size()];
MS_proj_thumbs_array = MS_proj_thumbs.toArray(MS_proj_thumbs_array);
// add _ID column to Images.Media projection, for use in JOIN
MS_proj.add("_ID");
String[] MS_proj_array = new String[MS_proj.size()];
MS_proj_array = MS_proj.toArray(MS_proj_array);
Uri baseUri;
// first, get cursor from MediaStore.Images.Thumbnails containing all thumbnails
baseUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
Log.v("JOAKIM", "Thumb: order by " + PhotoContract.ThumbEntry.COLUMN_DATE);
Cursor c_thumbs = getContext().getContentResolver().query(baseUri, MS_proj_thumbs_array, null, null, PhotoContract.ThumbEntry.COLUMN_IMAGE_ID);
if (c_thumbs == null || !c_thumbs.moveToFirst()) {
Log.v("JOAKIM", "MediaStore.Thumbnails cursor contains no data...");
return null;
}
// then, get cursor from MediaStore.Images.Media (for TITLE and DESCRIPTION etc)
// add _ID column to query
baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor c_images = getContext().getContentResolver().query(baseUri, MS_proj_array, null, null, PhotoContract.ThumbEntry.COLUMN_IMAGE_PK);
if (c_images == null || !c_images.moveToFirst()) {
Log.v("JOAKIM", "MediaStore.Images cursor contains no data...");
return null;
}
// join these and return
// the join is on images._ID = thumbnails.IMAGE_ID
CursorJoiner joiner = new CursorJoiner(
c_thumbs, new String[] { PhotoContract.ThumbEntry.COLUMN_IMAGE_ID },
c_images, new String[] { PhotoContract.ThumbEntry.COLUMN_IMAGE_PK }
);
MatrixCursor retCursor = new MatrixCursor(projection);
/*
Does a join on two cursors using the specified columns.
The cursors must already be sorted on each of the specified columns in ascending order.
This joiner only supports the case where the tuple of key column values is unique.
*/
for (CursorJoiner.Result joinerResult : joiner) {
switch (joinerResult) {
case LEFT:
// handle case where a row in cursorA is unique
break;
case RIGHT:
// handle case where a row in cursorB is unique
break;
case BOTH:
// handle case where a row with the same key is in both cursors
retCursor.addRow(new Object[]{
c_thumbs.getLong(0), // ID
c_thumbs.getString(1), // data
c_thumbs.getLong(2), // image id
c_images.getString(0), // title
c_images.getString(1), // desc
c_images.getLong(2) // date
});
break;
}
}
// https://stackoverflow.com/questions/12065606/getcontentresolver-query-cause-cursorwrapperinner-warning
c_thumbs.close();
c_images.close();
//retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
}
return null;
}
}
Related
I have an app that populates from a pre-existing SQLite database. I am now in need of obtaining the rowID (_id) when a list item is clicked. I think that I did not set my app up properly to be able to do that. I have had people provide me with input on what to do but I can't seem to understand it when trying to apply it to my app. Can someone please provide an example using my code? I would really appreciate it.
Here is my model class:
package com.mypackage.myapp.model;
import android.database.Cursor;
public class Verse {
private Cursor verseCursor;
private String verseNotificationString;
private String verseTitleString;
private int dBrowIdInt;
private String bookNameString;
private String chapterNumberString;
private String verseNumberString;
private String verseString;
public Verse(Cursor cursor, String bookNameString, String chapterNumberString, String verseNumberString, String verseString) {
verseCursor = cursor;
verseTitleString = bookNameString + " " + chapterNumberString + ":" + verseNumberString;
verseNotificationString = verseString;
}
public Verse(int dBrowId) {
dBrowIdInt = dBrowId;
}
public Cursor getVerseCursor() {
return verseCursor;
}
public void setVerseCursor(Cursor verseCursor) {
this.verseCursor = verseCursor;
}
public String getVerseTitleString() {
return verseTitleString;
}
public String getNotificationString() {
return verseNotificationString;
}
public Integer getDbRowId() {
return dBrowIdInt;
}
public void setNotificationString(String notificationString) {
this.verseNotificationString = notificationString;
}
public void setTitleString(String titleString) {
this.verseTitleString = titleString;
}
}
Here is my custom adapter:
package com.mypackage.myapp;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
public class VerseAdapter extends ArrayAdapter<String> {
private Context mContext;
private int mResource1;
private int mResource2;
public List<String> mVerses;
private List<Long> mRowId;
private TextView mVerseTextView;
private TextView mVerseNumberTextView;
private TextView mRowIdTextView;
private boolean mNightModeSwitchState;
private boolean mNightModeTwoSwitchState;
public VerseAdapter(Context context, int resource1, List<String>
verses, List<Long> rowId) {
super(context, resource1, verses);
this.mContext = context;
this.mResource1 = resource1;
this.mVerses = verses;
this.mRowId = rowId;
}
#Override
public int getCount() {
return mVerses.size();
}
#Override
public long getItemId(int position) {
return (position);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView,
#NonNull ViewGroup parent) {
View listItem = convertView;
int pos = position + 1;
if (listItem == null) {
listItem =
LayoutInflater.from(mContext).inflate(mResource1, parent, false);
}
//mRowIdTextView = (TextView)
listItem.findViewById(R.id.rowId);
//mRowIdTextView.setText(String.valueOf(getItemId(position)));
//mRowIdTextView.setText(String.valueOf(mRowId.get(position)));
mVerseNumberTextView = (TextView)
listItem.findViewById(R.id.verseNumber);
mVerseNumberTextView.setText(String.valueOf(pos) + " ");
mVerseTextView = (TextView)
listItem.findViewById(R.id.verseWords);
mVerseTextView.setText(mVerses.get(position));
SharedPreferences nightModeSwitchState =
getContext().getSharedPreferences("SettingsActivity", 0);
mNightModeSwitchState =
nightModeSwitchState.getBoolean("NightModeSwitchState", false);
SharedPreferences rowPosition =
getContext().getSharedPreferences("RowPosition", 0);
rowPosition.edit().putInt("RowPositionSqlite",
position).apply();
return listItem;
}
}
Here is my onListItemClick mehtod in the class that I need to access the rowID from (You can see some stuff that I tried and didn't work commented out):
mListView.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View
view, int position, long id) {
String selected = (String)
mListView.getItemAtPosition(position);
mVerseTextView = findViewById(R.id.verseWords);
mVerseNumberTextView = findViewById(R.id.verseNumber);
mAdapterView = adapterView;
mPositionForRow = position;
//mIdLong = id;
// VerseAdapter verseAdapter = (VerseAdapter)
adapterView.getAdapter();
// mSelectedVerse = (VerseForId)
mListView.getItemAtPosition(position);
// mDbRowId = mSelectedVerse.getDbRowId();
// mIdLong = verseAdapter.getItemId(position);
// mRowIdString = String.valueOf(id);
// VerseAdapter da = (VerseAdapter)
adapterView.getAdapter();
//mRowIdString =
String.valueOf(da.mVerses.get(position).getId());
// Toast.makeText(BibleBookVersesOldTestActivity.this,
mRowIdString + " id", Toast.LENGTH_LONG).show();
mBookCopied =
mVerseHeaderBookNameTextView.getText().toString();
mChapterNumberCopied =
Integer.toString(mChapterSelected + 1);
mVerseNumberCopied =
mVerseNumberTextView.getText().toString();
mPosition = position + 1;
mCopiedVerseListItem = mBookCopied + " " +
mChapterNumberCopied + ":" + mPosition + "\n\n" + selected;
showMenuVerseAction(view);
}
});
I know that I need to do something in my model class and custom adapter to set it up to be able to retrieve the database rowID onlistitemclick. Can someone possibly give me an example using my code? Thank you for your help.
*******Addition.... this is my Databaseaccess class.... well one section of it where I draw verses from a certain book from the SQLite Database. I have adjusted the other class that populates the list and therefor had to change the below operation to take in the model class Verse instead of String in the list... the problem I have is that the line below that reads list.add(cursor.getString(6)) where the (6) refers to the column index where to pull the verse from... gives an error that I can't apply that getString to Verse... how do I resolve this?
public List<Verse> getVersesChapterOne() {
List<Verse> list = new ArrayList<>();
Cursor cursor = database.rawQuery("SELECT * FROM bookcombinedfull
LIMIT 31", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
list.add(cursor.getString(6));
cursor.moveToNext();
}
cursor.close();
return list;
}
One idea is to replace the Custom Adapter's list from String to your model Verse. In this way, you can use the .getItem() to retrieve whatever information you want from your model class.
// public class VerseAdapter extends ArrayAdapter<String> {
public class VerseAdapter extends BaseAdapter {
public List<String> mVerses;
// public VerseAdapter(Context context, int resource1, List<String> verses, List<Long> rowId) {
public VerseAdapter(Context context, int resource1, List<Verse> verses) {
//...
mVerses = verses;
//...
#Override
public Object getItem(int i) {
return (Verse)mList.get(i);
}
// ...
// In your MainActivity.java, do this to get your item:
Verse verse = (Verse) mAdapter.getItem(position);
Log.d(TAG, verse.getVerseTitleString());
i'm trying to undestand Content Provider,but i stuck in one thing,
notification of cursor didn't work,if i update cursor in query method everything works fine.Where i get wrong.Thank you! This is full source code
https://github.com/denmariupol/StartAndroid/tree/master/lesson101_contentprovider_creation_h/src/main
MainActivity
package com.example.lesson101_contentprovider_creation_h;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.database.Cursor;
import android.databinding.DataBindingUtil;
import android.net.Uri;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;
import com.example.lesson101_contentprovider_creation_h.databinding.ActivityMainBinding;
import com.example.lesson101_contentprovider_creation_h.interfaces.IUpdateCursor;
import com.example.lesson101_contentprovider_creation_h.fragments.Insert;
import com.facebook.stetho.Stetho;
import java.util.ArrayList;
public class MainActivity extends FragmentActivity implements IUpdateCursor {
public final static Uri PROVIDER_URI = Uri.parse("com.example.lesson101_contentprovider_creation_h");
private Cursor cursor;
private MyAdapter scAdapter;
private ActivityMainBinding mainActivity;
private OnClickListener clickListener;
private int colId;
private int colText;
private ArrayList<Integer> chekedItems = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stethoInit();
mainActivity = DataBindingUtil.setContentView(this, R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
cursor = getContentResolver().query(MyProvider.CONTENT_URI, null, null, null, null, null);
}
colId = cursor.getColumnIndex(MyProvider.ID);
colText = cursor.getColumnIndex(MyProvider.TEXT);
String[] from = new String[]{MyProvider.ID, MyProvider.TEXT};
int[] to = new int[]{R.id.itemId, R.id.itemText};
scAdapter = new MyAdapter(this, R.layout.item, cursor, from, to, 0);
mainActivity.listItem.setAdapter(scAdapter);
scAdapter.notifyDataSetChanged();
mainActivity.listItem.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final View v = view;
final LinearLayout itemUpdateLayout = (LinearLayout)view.findViewById(R.id.itemUpdateLayout);
final LinearLayout itemViewLayout = (LinearLayout)view.findViewById(R.id.itemViewLayout);
TextView idView = (TextView)view.findViewById(R.id.itemId);
TextView textView = (TextView)view.findViewById(R.id.itemText);
final EditText editText = (EditText)view.findViewById(R.id.updateTextField);
Button updateButton = (Button)view.findViewById(R.id.updateRecButton);
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d("!!!","onTextChanged -> "+s.toString());
// ed
}
#Override
public void afterTextChanged(Editable s) {
}
});
final String updId = idView.getText().toString();
updateButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ContentValues cv = new ContentValues();
String text = editText.getText().toString();
Log.d("!!!","clicked text -> "+editText.getText().toString());
if(text.length() > 0) {
cv.put(MyProvider.TEXT, text);
Uri newUri = ContentUris.withAppendedId(MyProvider.CONTENT_URI,Long.valueOf(updId));
getContentResolver().update(newUri, cv,null,null);
// Cursor cursor = null;
// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
// cursor = getContentResolver().query(MyProvider.CONTENT_URI,null,null,null,null,null);
// }
// updateCursor(cursor);
}
itemUpdateLayout.setVisibility(View.GONE);
itemViewLayout.setVisibility(View.VISIBLE);
}
});
editText.setText(textView.getText());
itemUpdateLayout.setVisibility(View.VISIBLE);
itemViewLayout.setVisibility(View.INVISIBLE);
}
});
mainActivity.insert.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment insertFragment = new Insert();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, insertFragment);
ft.addToBackStack(null);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
});
mainActivity.delete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(chekedItems.size() > 0){
for (int i = 0; i < chekedItems.size(); i++) {
Uri newUri = ContentUris.withAppendedId(MyProvider.CONTENT_URI,chekedItems.get(i));
getContentResolver().delete(newUri,null,null);
// Cursor cursor = null;
// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
// cursor = getContentResolver().query(MyProvider.CONTENT_URI,null,null,null,null,null);
// }
// updateCursor(cursor);
}
chekedItems.clear();
}else{
Toast.makeText(MainActivity.this,"Nothing selected",Toast.LENGTH_SHORT).show();
}
}
});
}
private void stethoInit() {
// Create an InitializerBuilder
Stetho.InitializerBuilder initializerBuilder =
Stetho.newInitializerBuilder(this);
// Enable Chrome DevTools
initializerBuilder.enableWebKitInspector(
Stetho.defaultInspectorModulesProvider(this)
);
// Enable command line interface
initializerBuilder.enableDumpapp(
Stetho.defaultDumperPluginsProvider(this)
);
// Use the InitializerBuilder to generate an Initializer
Stetho.Initializer initializer = initializerBuilder.build();
// Initialize Stetho with the Initializer
Stetho.initialize(initializer);
}
#Override
public void updateCursor(Cursor newCusor) {
scAdapter.changeCursor(newCusor);
scAdapter.notifyDataSetChanged();
//hide keyboard
View view = this.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
private class MyAdapter extends SimpleCursorAdapter{
private int layout;
public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
this.layout = layout;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
final String id = cursor.getString(colId);
String title = cursor.getString(colText);
TextView idView = (TextView)view.findViewById(R.id.itemId);
idView.setText(id);
TextView textView = (TextView)view.findViewById(R.id.itemText);
textView.setText(title);
CheckBox checkBox = (CheckBox)view.findViewById(R.id.itemCheckBox);
checkBox.setChecked(false);
checkBox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(!chekedItems.contains(Integer.valueOf(id))){
chekedItems.add(Integer.valueOf(id));
}else{
chekedItems.remove(chekedItems.indexOf(Integer.valueOf(id)));
}
}
});
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = getLayoutInflater().inflate(layout,parent,false);
return view;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return getCount();
}
}
}
Insert Fragment
package com.example.lesson101_contentprovider_creation_h.fragments;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.lesson101_contentprovider_creation_h.MainActivity;
import com.example.lesson101_contentprovider_creation_h.MyProvider;
import com.example.lesson101_contentprovider_creation_h.R;
import com.example.lesson101_contentprovider_creation_h.databinding.FragmentInsertBinding;
import com.example.lesson101_contentprovider_creation_h.interfaces.IUpdateCursor;
/**
* A simple {#link Fragment} subclass.
*/
public class Insert extends Fragment{
Activity activity;
public Insert() {
// Required empty public constructor
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.activity = (Activity)context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final FragmentInsertBinding insertBinding = DataBindingUtil.inflate(inflater,R.layout.fragment_insert,container,false);
View v = insertBinding.getRoot();
insertBinding.insertRecButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ContentValues cv = new ContentValues();
String text = insertBinding.insertTextField.getText().toString();
if(text.length() > 0) {
cv.put(MyProvider.TEXT, text);
getContext().getContentResolver().insert(MyProvider.CONTENT_URI, cv);
getActivity().getSupportFragmentManager().beginTransaction().remove(Insert.this).commit();
insertBinding.insertTextField.clearFocus();
// Cursor cursor = null;
// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
// cursor = getContext().getContentResolver().query(MyProvider.CONTENT_URI,null,null,null,null,null);
// }
// ((IUpdateCursor)activity).updateCursor(cursor);
}
}
});
// Inflate the layout for this fragment
return v;
}
// public interface IUpdateCursor{
// void updateCursor(Cursor newCursor);
// }
}
MyProvider
package com.example.lesson101_contentprovider_creation_h;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
/**
* Created by den on 2017-03-31.
*/
public class MyProvider extends ContentProvider{
private final String DB_NAME = "my";
private int DB_VERSION = 1;
private static final String AUTHORITY = "com.example.lesson101_contentprovider_creation_h";
private static final String PATH = "table";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);
public static final String DB_TABLE = "MYTABLE";
public static final String ID = "_id";
public static final String TEXT = "text";
private final String CREATE_DB = "CREATE TABLE " + DB_TABLE + " ("
+ ID + " integer primary key autoincrement, "
+ TEXT + " text);";
private DBHelper dbHelper;
private SQLiteDatabase database;
private static final int TABLE = 1;
private static final int TABLE_ID = 2;
static final String CONTACT_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd."
+ AUTHORITY + "." + PATH;
private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
uriMatcher.addURI(AUTHORITY, PATH, TABLE);
uriMatcher.addURI(AUTHORITY, PATH + "/#", TABLE_ID);
}
#Override
public boolean onCreate() {
dbHelper = new DBHelper(getContext());
return true;
}
#Nullable
#Override
public Cursor query(#NonNull Uri uri, #Nullable String[] projection,
#Nullable String selection, #Nullable String[] selectionArgs, #Nullable String sortOrder) {
database = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)){
case TABLE:
sortOrder = ID;
break;
case TABLE_ID:
String id = uri.getLastPathSegment();
sortOrder = TEXT;
break;
}
Cursor cursor = database.query(DB_TABLE,projection,selection,selectionArgs,null,null,sortOrder);
Log.d("!!!","query -> "+uri.toString());
cursor.setNotificationUri(getContext().getContentResolver(),CONTENT_URI);
return cursor;
}
#Nullable
#Override
public String getType(#NonNull Uri uri) {
switch (uriMatcher.match(uri)){
case TABLE:
break;
case TABLE_ID:
return CONTACT_CONTENT_ITEM_TYPE;
}
return null;
}
#Nullable
#Override
public Uri insert(#NonNull Uri uri, #Nullable ContentValues values) {
database = dbHelper.getWritableDatabase();
Log.d("!!!","insert -> "+uri.toString());
if(uriMatcher.match(uri) != TABLE)
throw new IllegalArgumentException("Wrong URI: "+uri);
long id = database.insert(DB_TABLE,null,values);
Uri resultUri = ContentUris.withAppendedId(CONTENT_URI,id);
Log.d("!!!","insert after -> "+resultUri.toString());
getContext().getContentResolver().notifyChange(resultUri,null);
return resultUri;
}
#Override
public int delete(#NonNull Uri uri, #Nullable String selection, #Nullable String[] selectionArgs) {
database = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)){
case TABLE:
break;
case TABLE_ID:
String id = uri.getLastPathSegment();
selection = ID + " = " + id;
break;
}
int c = database.delete(DB_TABLE,selection,selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return c;
}
#Override
public int update(#NonNull Uri uri, #Nullable ContentValues values, #Nullable String selection, #Nullable String[] selectionArgs) {
database = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)){
case TABLE:
break;
case TABLE_ID:
String id = uri.getLastPathSegment();
selection = ID + " = " +id;
Log.d("!!!",id);
break;
}
int c = database.update(DB_TABLE,values,selection,null);
getContext().getContentResolver().notifyChange(uri, null);
return c;
}
private class DBHelper extends SQLiteOpenHelper{
public DBHelper(Context context) {
super(context,DB_NAME,null,DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
updateDB(db,0,DB_VERSION);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private void updateDB(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion < 1)
db.execSQL(CREATE_DB);
}
}
}
Did you check if the uri used in setNotificationUri is matching the ones used in the getContext().getContentResolver().notifyChange()?
Cursor.setNotificationUri()
will register for the underline uri for the
getContext().getContentResolver().notifyChange(uri, null);
which is called when such as at ContentProvider's insert(), update() and delete() calls, so the Cursor (has setNotificationUri()) will be notified.
If you are using CursorAdapter, by default, CursorAdapter objects will get this notification issued by getContext().getContentResolver().notifyChange.
Another thing to make sure not to do cursor.close(), the close() will cause unregister the content observer which was registered by CursorLoader. And the cursor closing is managed by CursorLoader.
I'm trying to create a patient registration app in android but I'm currently stuck on how to achieved a multiple table to relate with and add to loader callback method.
The First table is for patient fullname.
And the Second table is for patient information foreign key to the id of the patient_fullname table.
Can someone here explain or help me on how to achieved this output?
Appreciate for any help.
PatienDBOpenHelper.java
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class PatientDBOpenHelper extends SQLiteOpenHelper{
//Constants for db name and version
private static final String LOGTAG = "DENTALAPP";
private static final String DATABASE_NAME = "dental.db";
private static final int DATABASE_VERSION = 1;
//Constants for identifying table and columns
public static final String TABLE_PATIENT = "patient";
public static final String PATIENT_ID = "_id";
public static final String PATIENT_NAME = "nameInfo";
public static final String PATIENT_GENDER = "genderInfo";
public static final String PATIENT_CREATED = "patientCreated";
/*I will put my desired table structure here
_id
patientId
address
occupation
etc....
*/
public static final String[] ALL_COLUMNS = {PATIENT_ID, PATIENT_NAME, PATIENT_GENDER,PATIENT_CREATED};
//SQL to create table
private static final String TABLE_CREATE_PATIENT =
"CREATE TABLE " + TABLE_PATIENT + " (" +
PATIENT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
PATIENT_NAME + " TEXT, " +
PATIENT_GENDER + " TEXT, " +
PATIENT_CREATED + " TEXT default CURRENT_TIMESTAMP" +
")";
/*
Will also add query statement here for another table.
*/
public PatientDBOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
/*
Add the creation of other table.
*/
sqLiteDatabase.execSQL(TABLE_CREATE_PATIENT);
Log.i(LOGTAG,"Table Created!");
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
/*
Add the query of my additional drop table.
*/
sqLiteDatabase.execSQL("DROP TABLE IF EXIST " + TABLE_PATIENT);
onCreate(sqLiteDatabase);
}
}
PatientDataSource.java
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.bloxofcode.multipletabs.model.Patient;
public class PatientDataSource {
private static final String LOGTAG = "DENTALAPP";
SQLiteOpenHelper dbhelper;
SQLiteDatabase database;
public PatientDataSource(Context context){
dbhelper = new PatientDBOpenHelper(context);
}
public void open(){
Log.i(LOGTAG,"Database open");
database = dbhelper.getWritableDatabase();
}
public void close(){
Log.i(LOGTAG,"Database close");
dbhelper.close();
}
public Patient create(Patient patient){
ContentValues values = new ContentValues();
values.put(PatientDBOpenHelper.PATIENT_NAME,patient.getPatientFullName());
values.put(PatientDBOpenHelper.PATIENT_GENDER,patient.getPatientGender());
long id = database.insert(PatientDBOpenHelper.TABLE_PATIENT,null,values);
patient.setId(id);
return patient;
}
}
Tab1.java
public class Tab1 extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{
private ImageButton imgButton;
private CustomDialog customDialog;
private TextView tvNoRecord;
private ImageView imgNoRecord;
private CursorAdapter cursorAdapter;
PatientDataSource patientDataSource;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
patientDataSource = new PatientDataSource(getActivity());
patientDataSource.open();
final View v =inflater.inflate(R.layout.tab_1,container,false);
imgButton = (ImageButton) v.findViewById(R.id.imageButton);
imgNoRecord = (ImageView) v.findViewById(R.id.imgNoRecord);
tvNoRecord = (TextView) v.findViewById(R.id.tvNoRecord);
//Creating ImageButton
imgButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
customDialog = new CustomDialog(getActivity());
customDialog.setDialogResult(new OnMyDialogResult() {
#Override
public void finish(String resultName, String resultGender) {
if (!resultName.isEmpty()){
Log.d("TestingUnit","asdadasdsa");
Patient patient = new Patient();
patient.setPatientFullName(resultName);
patient.setPatientGender(resultGender);
patientDataSource.create(patient);
restartLoader();
}
listPatient(v);
}
});
customDialog.show();
}
});
listPatient(v);
return v;
}
private void listPatient(View v){
cursorAdapter = new PatientCursorAdapter(getActivity(),null,0 );
ListView list = (ListView) v.findViewById(android.R.id.list);
list.setAdapter(cursorAdapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String info = ((TextView) view.findViewById(R.id.tvName)).getText().toString();
Intent i = new Intent(getContext(), UserInfoActivity.class);
i.putExtra("PersonName", info);
startActivity(i);
}
});
getLoaderManager().initLoader(0,null,this);
}
private void restartLoader(){
getLoaderManager().restartLoader(0,null,this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), PatientProvider.CONTENT_URI,null,null,null,null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(data.getCount() > 0){
imgNoRecord.setVisibility(View.INVISIBLE);
tvNoRecord.setVisibility(View.INVISIBLE);
}else{
imgNoRecord.setVisibility(View.VISIBLE);
tvNoRecord.setVisibility(View.VISIBLE);
}
cursorAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
#Override
public void onResume() {
super.onResume();
patientDataSource.open();
}
#Override
public void onPause() {
super.onPause();
patientDataSource.close();
}
}
This is where i will get the 1st table(patient full name):
This is where the 2nd table will show its data(patient info):
I have an activity with a tablayout. When the activity is created, the viewpageradapter is created and adds 3 instances of the same fragment class to it. Then, then, I set the adapter to the view pager.
I know that the fragment addition is happening correctly because my fragment executes an asyncTask and its logging statements appear in the console. For some reason, when I start the activity, I can see the app bar and the widget displaying the tabs, but the space where the fragment should appear is empty. What am I doing wrong?
This is my code:
MainActivity
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private final String LIST_TAG = MovieListFragment.class.getSimpleName();
private final String DETAIL_TAG = DetailActivityFragment.class.getSimpleName();
private final String POPULAR = "POPULAR";
private final String HIGHEST_RATED = "HIGHEST RATED";
private final String FAVOURITE = "FAVOURITE";
private boolean mTwoPane;
private TabLayout mTabLayout;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//We check if the layout selected has two fragments
if (findViewById(R.id.movie_detail_container) != null) {
//If it has two, we update our member variable
mTwoPane = true;
/*If the activity has been recently created, we replace the placeholder
frameview with the actual detail fragment
*/
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(
R.id.movie_detail_container,
new DetailActivityFragment(),
DETAIL_TAG
).commit();
}
} else {
mTwoPane = false;
}
mViewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(mViewPager);
mTabLayout = (TabLayout) findViewById(R.id.tabs);
mTabLayout.setupWithViewPager(mViewPager);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
/*If it's the first time we launch the activity, we create a fragment
and tag it so we have a reference to find it later
*/
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
MovieListFragment popular = new MovieListFragment();
MovieListFragment highestRated = new MovieListFragment();
MovieListFragment favourites = new MovieListFragment();
populateFragment(popular);
populateFragment(highestRated);
populateFragment(favourites);
adapter.addFragment(popular, POPULAR);
adapter.addFragment(highestRated, HIGHEST_RATED);
adapter.addFragment(favourites, FAVOURITE);
viewPager.setAdapter(adapter);
}
private void populateFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, fragment)
.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.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//We identify the option clicked and act accordingly
switch (id) {
/* Not necessary at this stage of the project. Will be
populated later.
*/
case R.id.action_settings: {
return true;
}
/* If the sort method is changed we start an asynchronous task
and fetch the appropriate movies.
*/
case R.id.sort_popularity: {
MovieListFragment.setmSortOrder("popularity.desc");
MovieListFragment movieListFragment = (MovieListFragment)
getSupportFragmentManager().findFragmentByTag(LIST_TAG);
movieListFragment.retrieveMovies();
break;
}
case R.id.sort_highest_Rating: {
MovieListFragment.setmSortOrder("vote_average.desc");
MovieListFragment movieListFragment = (MovieListFragment)
getSupportFragmentManager().findFragmentByTag(LIST_TAG);
movieListFragment.retrieveMovies();
break;
}
}
return super.onOptionsItemSelected(item);
}
}
ViewPagerAdapter
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.ArrayList;
import java.util.List;
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position)
{
return new MovieListFragment();
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
MovieListFragment
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* A placeholder fragment containing a simple view.
*/
public class MovieListFragment extends Fragment {
//Defining size params for the images in the gridview
private final int IMAGE_WIDTH = 450;
private final int IMAGE_HEIGHT = 675;
private static String mSortOrder = "popularity.desc";
public final static String EXTRA_MOVIE = "com.example.android.movierating.EXTRA_MOVIE";
private final String LOG_TAG = MovieListFragment.class.getSimpleName();
MovieAdapter mMovieAdapter;
private LayoutInflater mInflater;
public MovieListFragment() {
}
#Override
public void onCreate(Bundle SavedInstanceState) {
super.onCreate(SavedInstanceState);
// We want to add options to the Menu bar.
setHasOptionsMenu(true);
}
public static String getmSortOrder() {
return mSortOrder;
}
public static void setmSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.movielist_fragment, menu);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mInflater = inflater;
// We inflate and store the rootView
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// We sotre the gridview and set a custom adapter to it. It is defined below
GridView gridView = (GridView) getActivity().findViewById(R.id.gridview);
mMovieAdapter = new MovieAdapter(
getContext(),
R.id.image_thumbnail,
new ArrayList<Movie>()
);
gridView.setAdapter(mMovieAdapter);
/* The gridView will react to a user clicking on it by creating
an intent and populating it with the movie object. That object
will provide the data necessary to display facts about the movie
*/
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Movie movie = mMovieAdapter.getItem(position);
Intent detailIntent = new Intent(getActivity(), DetailActivity.class)
.putExtra(EXTRA_MOVIE, (Parcelable) movie);
startActivity(detailIntent);
}
});
return rootView;
}
public void retrieveMovies() {
if (getmSortOrder() == "popularity.desc" || getmSortOrder() == "vote_average.desc") {
FetchMoviesTask moviesTask = new FetchMoviesTask();
String sortOrderArray[] = {mSortOrder};
moviesTask.execute(sortOrderArray);
}
}
#Override
public void onStart() {
super.onStart();
retrieveMovies();
}
// Custom adapter to display Movies on a gridView
public class MovieAdapter extends ArrayAdapter<Movie> {
//Context member variable
private Context mContext;
//Constructor
public MovieAdapter(Context context, int imgViewResourceId,
ArrayList<Movie> items) {
super(context, imgViewResourceId, items);
mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
view = mInflater.inflate(R.layout.fragment_main,null);
} else {
view = convertView;
}
ImageView imageView = (ImageView) view.findViewById(R.id.image_thumbnail);
TextView textView = (TextView) view.findViewById(R.id.overlay_text);
String url = getItem(position).getUrlPath();
Picasso.with(mContext)
.load(url)
.resize(IMAGE_WIDTH,IMAGE_HEIGHT)
.centerCrop()
.into(imageView);
String movieTitle = getItem(position).getOriginalTitle();
textView.setText(movieTitle);
textView.setBackgroundColor(getResources().getColor(R.color.translucid_black));
textView.setTextColor(getResources().getColor(R.color.opaque_white));
return view;
}
}
// Nested class to fetch the Json information about the movies
public class FetchMoviesTask extends AsyncTask<String, Void, List<Movie>> {
//Log tag for debugging purposes
private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();
// Method to take a JSON string and return a list of Movie
// objects.
private List<Movie> parseJSONtoArrayList(String stringJSON)
throws JSONException{
// String constants and the arraylist holding the results
final String MDB_RESULTS = "results";
final String MDB_ID = "id";
final String MDB_PATH = "poster_path";
final String MDB_TITLE = "original_title";
final String MDB_SYNOPSIS = "overview";
final String MDB_RATING = "vote_average";
final String MDB_VOTE_COUNT = "vote_count";
final String MDB_RELEASE = "release_date";
List<Movie> movieArrayList = new ArrayList<>();
// We turn the results into a JSONObject and we extract the JSONObjects
// into an array of objects.
JSONObject dataJSON = new JSONObject(stringJSON);
JSONArray movieArray = dataJSON.getJSONArray(MDB_RESULTS);
/* We iterate over the array of JSONObjects, we create a new
Movie object and we append it to the arraylist holding the
results.
*/
for (int i=0; i<movieArray.length(); i++) {
// Select a JSONObject in every iteration.
JSONObject target = movieArray.getJSONObject(i);
/* Create a Movie Object by retrieving the necessary elements
of the JSONObject
*/
Movie movie = new Movie(
target.getInt(MDB_ID),
createURL(target.getString(MDB_PATH)),
target.getString(MDB_TITLE),
target.getString(MDB_SYNOPSIS),
Float.parseFloat(target.getString(MDB_RATING)),
Integer.parseInt(target.getString(MDB_VOTE_COUNT)),
target.getString(MDB_RELEASE)
);
// Once we have created our object, we add it to the arrayList
movieArrayList.add(movie);
}
return movieArrayList;
}
/* Transform a relative path provided by the API into a fully functional
URL path.
*/
private String createURL(String relativePath) {
final String BASE_IMAGE_URL = "http://image.tmdb.org/t/p/";
final String PIX_MEASURE = "w185";
return BASE_IMAGE_URL + PIX_MEASURE + relativePath;
}
#Override
protected List<Movie> doInBackground(String... params) {
// Our default sorting parameter, request declaration,
// reader and empty string
String sortMethod = params[0];
HttpURLConnection connection = null;
BufferedReader reader = null;
String moviesJSON = null;
try {
// We build the URI
final String BASE_URL =
"http://api.themoviedb.org/3/discover/movie?";
final String API_KEY = "api_key";
final String SORT = "sort_by";
String uri = Uri.parse(BASE_URL)
.buildUpon().appendQueryParameter(SORT, sortMethod)
.appendQueryParameter(API_KEY, getString(R.string.ApiKey))
.build().toString();
URL url = new URL(uri);
//Create the request and open the connection
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
// Create objects to hold the results of the API call
InputStream inputStream = connection.getInputStream();
StringBuilder builder = new StringBuilder();
// If we don't receive anything, we just return
if (inputStream == null) {
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
// We write the api call results into the string builder
String line;
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
}
// We check that the result is not empty
if (builder.length() == 0) {
return null;
}
moviesJSON = builder.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "There was a problem fetching the movies");
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (reader !=null) {
try {
reader.close();
} catch (IOException e) {
Log.e(LOG_TAG, "We found a problem while closing the reader");
e.printStackTrace();
}
}
}
try {
return parseJSONtoArrayList(moviesJSON);
} catch (JSONException e) {
Log.e(LOG_TAG, e.toString());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(List<Movie> movies) {
super.onPostExecute(movies);
if (movies != null) {
// Every time we call this task, we flush the Movies in the adaptor
// And fill it up again with the results of the API call.
mMovieAdapter.clear();
Log.e(LOG_TAG, movies.toString());
mMovieAdapter.addAll(movies);
}
}
}
}
Thank you very much in advance
I need to load a large dataset from a sqlite database. This will take too much of time to load the data. Therefore I used LoadMorelistView library to load with pagination.
I followed below link and successfully load the data from hard coded list.
pull to refresh and loadmore listview like facebook
But when I tried to load from sqlite database I got the following error.
// The constructor ArrayAdapter(Activity, int, ArrayList) is Undefined
I searched the google as well as stackoverflow. But unable to find a solution.
Please find the code snippet which I used to load the data,
Code for the list loading fragment. (FragmentThree.java)
package com.load.more.list.view;
import java.util.ArrayList;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.costum.android.widget.LoadMoreListView;
import com.costum.android.widget.LoadMoreListView.OnLoadMoreListener;
import com.load.more.list.model.Customer;
import com.load.more.list.data.CustomerDS;
import com.load.more.list.data.DatabaseHelper;
import android.app.Fragment;
import com.load.more.list.control.CustomerAdapter;
public class FragmentThree extends Fragment {
View view;
LoadMoreListView lyt;
ArrayAdapter<String> files;
ArrayList<Customer> mListItems;
CustomerDS customerDS;
private DatabaseHelper dbHelper;
private int visibleThreshold = 20;
private int currentPage = 0;
private int previousTotal = 0;
private int firstVisibleItem = 0;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_three, container, false);
lyt = (LoadMoreListView) view.findViewById(R.id.lvRouteCustomers);
mListItems = customerDS.getAllCustomersFromTo(visibleThreshold,
firstVisibleItem);
// Following Error Thrown from here
// The constructor ArrayAdapter<String>(Activity, int,
// ArrayList<Customer>) is Undefined
files = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, mListItems);
lyt.setAdapter(files);
lyt.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
// TODO Auto-generated method stub
new LoadMoreDataTask().execute();
}
});
return view;
}
private class LoadMoreDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
if (isCancelled()) {
return null;
}
// Simulates a background task
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// Following Error Thrown from here
// The constructor ArrayAdapter<String>(Activity, int,
// ArrayList<Customer>) is Undefined
files = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, mListItems);
lyt.setAdapter(files);
return null;
}
#Override
protected void onPostExecute(Void result) {
files.notifyDataSetChanged();
// Call onLoadMoreComplete when the LoadMore task, has finished
lyt.onLoadMoreComplete();
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
// Notify the loading more operation has finished
lyt.onLoadMoreComplete();
}
}
}
Code for the database helper class. (DatabaseHelper)
package com.load.more.list.data;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
//database information
private static final String DATABASE_NAME = "fmcgDB.db";
private static final int DATABASE_VERSION = 1;
//TABLES
//Customer table
public static final String TABLE_CUSTOMER = "customer";
public static final String CUSTOMER_ID = "customer_id";
public static final String CUSTOMER_NO = "customer_no";
public static final String CUSTOMER_NAME = "customer_name";
public static final String CUSTOMER_CONTACT_PERSON = "customer_contact_person";
public static final String CUSTOMER_TELEPHONE_NO = "customer_telephone_no";
public static final String CUSTOMER_ADDRESS = "customer_address";
public static final String CUSTOMER_LONGITUDE = "customer_longitude";
public static final String CUSTOMER_LATITUDE = "customer_latitude";
public static final String CUSTOMER_TLP = "customer_tlp";
public static final String CUSTOMER_REP_ID = "customer_rep_id";
public static final String CUSTOMER_CATEGORY_ID = "cc_id";
public static final String CUSTOMER_OUTLET_TYPE_ID = "ot_id";
public static final String CUSTOMER_PERIPHERY_TYPE_ID = "pt_id";
public static final String CUSTOMER_VOLUME_ID = "volume_id";
public static final String CUSTOMER_MARKET_ID = "market_id";
private static final String CREATE_CUSTOMER_TABLE = "CREATE TABLE " + TABLE_CUSTOMER + " ("
+ CUSTOMER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ CUSTOMER_NO + " TEXT, "
+ CUSTOMER_NAME + " TEXT, "
+ CUSTOMER_CONTACT_PERSON + " TEXT, "
+ CUSTOMER_TELEPHONE_NO + " TEXT, "
+ CUSTOMER_ADDRESS + " TEXT, "
+ CUSTOMER_LONGITUDE + " REAL, "
+ CUSTOMER_LATITUDE + " REAL, "
+ CUSTOMER_TLP + " INTEGER, "
+ CUSTOMER_REP_ID + " INTEGER, "
+ CUSTOMER_CATEGORY_ID + " INTEGER, "
+ CUSTOMER_OUTLET_TYPE_ID + " INTEGER, "
+ CUSTOMER_PERIPHERY_TYPE_ID + " INTEGER, "
+ CUSTOMER_VOLUME_ID + " INTEGER, "
+ CUSTOMER_MARKET_ID + " INTEGER "
+");";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase arg0) { // this order must be followed when creating tables
arg0.execSQL(CREATE_CUSTOMER_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
arg0.execSQL("DROP TABLE IF EXISTS " + CREATE_CUSTOMER_TABLE);
onCreate(arg0);
}
}
Code for the sqlite data loading. (CustomerDS.java)
package com.load.more.list.data;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import com.load.more.list.model.Customer;
public class CustomerDS {
private SQLiteDatabase fmcgDB;
private DatabaseHelper dbHelper;
Context context;
public CustomerDS(Context context) {
this.context = context;
dbHelper = new DatabaseHelper(context);
}
public void open() throws SQLException {
fmcgDB = dbHelper.getWritableDatabase();
}
public ArrayList<Customer> getAllCustomersFromTo(int limit, int offset) {
if (fmcgDB == null) {
open();
} else if (!fmcgDB.isOpen()) {
open();
}
ArrayList<Customer> customersList = new ArrayList<Customer>();
// Newly Added
String selectQuery = "SELECT * FROM " + dbHelper.TABLE_CUSTOMER
+ " LIMIT " + limit + " OFFSET " + offset +"";
Cursor cursor = null;
try{
cursor = fmcgDB.rawQuery(selectQuery, null);
/*cursor = fmcgDB.query(dbHelper.TABLE_CUSTOMER, null, null, null,
null, null, null);
*/
while (cursor.moveToNext()) {
Customer customer = new Customer();
customer.setCustomer_id(cursor.getInt(cursor.getColumnIndex(dbHelper.CUSTOMER_ID)));
customer.setCustomer_no(cursor.getString((cursor.getColumnIndex(dbHelper.CUSTOMER_NO))));
customer.setCustomer_name(cursor.getString((cursor.getColumnIndex(dbHelper.CUSTOMER_NAME))));
customer.setCustomer_contact_person(cursor.getString((cursor.getColumnIndex(dbHelper.CUSTOMER_CONTACT_PERSON))));
customer.setCustomer_telephone_no(cursor.getString((cursor.getColumnIndex(dbHelper.CUSTOMER_TELEPHONE_NO))));
customer.setCustomer_address(cursor.getString((cursor.getColumnIndex(dbHelper.CUSTOMER_ADDRESS))));
customer.setCustomer_longitude(cursor.getDouble((cursor.getColumnIndex(dbHelper.CUSTOMER_LONGITUDE))));
customer.setCustomer_latitude(cursor.getDouble((cursor.getColumnIndex(dbHelper.CUSTOMER_LATITUDE))));
int TLP = cursor.getInt((cursor.getColumnIndex(dbHelper.CUSTOMER_TLP)));
if(TLP == 0){
customer.setCustomer_TLP_member(true);
}else{
customer.setCustomer_TLP_member(false);
}
customersList.add(customer);
}
}
finally {
if (cursor!=null) {
cursor.close();
}
fmcgDB.close();
return customersList;
}
}
}
Code for the Adapter Class. (CustomerAdapter.java)
package com.load.more.list.control;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.load.more.list.model.Customer;
import com.load.more.list.view.R;
public class CustomerAdapter extends ArrayAdapter<Customer> {
Context context;
ArrayList<Customer> customerList;
public CustomerAdapter(Context context, ArrayList<Customer> customerList){
super(context, R.layout.item_customer, customerList);
this.context = context;
this.customerList = customerList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.item_customer, parent, false);
TextView tvName = (TextView) row.findViewById(R.id.tvRouteCustomerListName);
TextView tvMarket = (TextView) row.findViewById(R.id.tvRouteCustomerListMarket);
TextView tvVolume = (TextView) row.findViewById(R.id.tvRouteCustomerListVolume);
tvName.setText(customerList.get(position).getCustomer_name());
return row;
}
}
Code for the Customer Object. (Customer.java)
package com.load.more.list.model;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.util.Log;
public class Customer {
private static final String TAG_CUSTOMER = "customers";
private static final String TAG_CUSTOMER_ID = "customer_id";
private static final String TAG_CUSTOMER_NO = "CustomerCode";
private static final String TAG_CUSTOMER_NAME = "CustomerName";
private static final String TAG_CUSTOMER_ADDRESS = "Address1";
private static final String TAG_CUSTOMER_CONTACT_PERSON = "ContactPersonName";
private static final String TAG_CUSTOMER_TELEPHONE_NO = "PhoneNo";
private static final String TAG_CUSTOMER_LATITUDE = "CustomerLatitude";
private static final String TAG_CUSTOMER_LONGITUDE = "CustomerLongitude";
private static final String TAG_CUSTOMER_IS_TLP = "Istlp";
private static final String TAG_CUSTOMER_REP_ID = "";
private static final String TAG_CUSTOMER_PT_ID = "PheriheryId";
private static final String TAG_CUSTOMER_CATEGORY_ID = "CatrgoryId";
private static final String TAG_CUSTOMER_OUTLETTYPE_ID = "OutletTypeId";
private static final String TAG_CUSTOMER_VOLUME_ID = "VolumeId";
private static final String TAG_CUSTOMER_MARKET_ID = "MarketId";
private int customer_id;
private String customer_no;
private String customer_name;
private String customer_contact_person;
private String customer_telephone_no;
private String customer_address;
private double customer_longitude;
private double customer_latitude;
private boolean customer_TLP_member;
public int getCustomer_id() {
return customer_id;
}
public void setCustomer_id(int customer_id) {
this.customer_id = customer_id;
}
public String getCustomer_name() {
return customer_name;
}
public void setCustomer_name(String customer_name) {
this.customer_name = customer_name;
}
public String getCustomer_contact_person() {
return customer_contact_person;
}
public void setCustomer_contact_person(String customer_contact_person) {
this.customer_contact_person = customer_contact_person;
}
public String getCustomer_telephone_no() {
return customer_telephone_no;
}
public void setCustomer_telephone_no(String customer_telephone_no) {
this.customer_telephone_no = customer_telephone_no;
}
public String getCustomer_address() {
return customer_address;
}
public void setCustomer_address(String customer_address) {
this.customer_address = customer_address;
}
public double getCustomer_longitude() {
return customer_longitude;
}
public void setCustomer_longitude(double customer_longitude) {
this.customer_longitude = customer_longitude;
}
public double getCustomer_latitude() {
return customer_latitude;
}
public void setCustomer_latitude(double customer_latitude) {
this.customer_latitude = customer_latitude;
}
public boolean isCustomer_TLP_member() {
return customer_TLP_member;
}
public void setCustomer_TLP_member(boolean customer_TLP_member) {
this.customer_TLP_member = customer_TLP_member;
}
public String getCustomer_no() {
return customer_no;
}
public void setCustomer_no(String customer_no) {
this.customer_no = customer_no;
}
}
Can anyone know how to solve this problem? If yes, please help me to solve this problem.
Thanks in advance.
Finally I solved the issue,.
I have changed the type of mListItems to
ArrayList<String> mListItems;
and the return type of getAllCustomersFromTo() to String array.
It solved my issue.
Final source code of the updated classes are shown below.
Code for the list loading fragment. (FragmentThree.java)
package com.load.more.list.view;
import java.util.ArrayList;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.costum.android.widget.LoadMoreListView;
import com.costum.android.widget.LoadMoreListView.OnLoadMoreListener;
import com.load.more.list.model.Customer;
import com.load.more.list.data.CustomerDS;
import com.load.more.list.data.DatabaseHelper;
import android.app.Fragment;
import com.load.more.list.control.CustomerAdapter;
public class FragmentThree extends Fragment {
View view;
LoadMoreListView lyt;
ArrayAdapter<String> files;
ArrayList<String> mListItems;
CustomerDS customerDS;
private DatabaseHelper dbHelper;
private int visibleThreshold = 20;
private int currentPage = 0;
private int previousTotal = 0;
private int firstVisibleItem = 0;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_three, container, false);
lyt = (LoadMoreListView) view.findViewById(R.id.lvRouteCustomers);
mListItems = customerDS.getAllCustomersFromTo(visibleThreshold,
firstVisibleItem);
files = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, mListItems);
lyt.setAdapter(files);
lyt.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
// TODO Auto-generated method stub
new LoadMoreDataTask().execute();
}
});
return view;
}
private class LoadMoreDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
if (isCancelled()) {
return null;
}
// Simulates a background task
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
files = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, mListItems);
lyt.setAdapter(files);
return null;
}
#Override
protected void onPostExecute(Void result) {
files.notifyDataSetChanged();
// Call onLoadMoreComplete when the LoadMore task, has finished
lyt.onLoadMoreComplete();
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
// Notify the loading more operation has finished
lyt.onLoadMoreComplete();
}
}
}
Code for the sqlite data loading. (CustomerDS.java)
package com.load.more.list.data;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import com.load.more.list.model.Customer;
public class CustomerDS {
private SQLiteDatabase fmcgDB;
private DatabaseHelper dbHelper;
Context context;
public CustomerDS(Context context) {
this.context = context;
dbHelper = new DatabaseHelper(context);
}
public void open() throws SQLException {
fmcgDB = dbHelper.getWritableDatabase();
}
public ArrayList<String> getAllCustomersFromTo(int limit, int offset) {
if (fmcgDB == null) {
open();
} else if (!fmcgDB.isOpen()) {
open();
}
ArrayList<String> customersList = new ArrayList<String>();
String selectQuery = "SELECT * FROM " + dbHelper.TABLE_CUSTOMER
+ " LIMIT " + limit + " OFFSET " + offset +"";
Cursor cursor = null;
try{
cursor = fmcgDB.rawQuery(selectQuery, null);
while (cursor.moveToNext()) {
customersList.add(cursor.getString((cursor.getColumnIndex(dbHelper.CUSTOMER_NAME))));
}
}
finally {
if (cursor!=null) {
cursor.close();
}
fmcgDB.close();
return customersList;
}
}
}