How to do multiple inserts in database using spring JDBC Template batch? - spring-jdbc

I need to insert thousands of records in the database at one go. I am using spring JDBC template in my application.
Below is the code I have written so far which executes all inserts at one go. So, if I ahve 10,000 users they are inserted at one go. But what I want is to execute them in batches say for example 500 records in one batch and so on.
#Override
public void saveBatch(final List<Employee> employeeList) {
final int batchSize = 500;
getJdbcTemplate().batchUpdate(QUERY_SAVE,
new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
Employee employee = employeeList.get(i);
ps.setString(1, employee.getFirstname());
ps.setString(2, employee.getLastname());
ps.setString(3, employee.getEmployeeIdOnSourceSystem());
}
#Override
public int getBatchSize() {
return employeeList.size();
}
});
}
How do I change the above code so that instead of employeeList.size() as the batch size can we have batch size as say 500, execute them and then next 500 and so on?
Please help.

I am not sure if you can do that using JDBC template alone. Maybe you could invoke the batchUpdate method in steps, by slicing up the big list into batch-sized chunks.
Have a look here:
#Override
public void saveBatch(final List<Employee> employeeList) {
final int batchSize = 500;
for (int j = 0; j < employeeList.size(); j += batchSize) {
final List<Employee> batchList = employeeList.subList(j, j + batchSize > employeeList.size() ? employeeList.size() : j + batchSize);
getJdbcTemplate().batchUpdate(QUERY_SAVE,
new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
Employee employee = batchList.get(i);
ps.setString(1, employee.getFirstname());
ps.setString(2, employee.getLastname());
ps.setString(3, employee.getEmployeeIdOnSourceSystem());
}
#Override
public int getBatchSize() {
return batchList.size();
}
});
}
}

I know it's a bit late but you could do something similar to what #adarshr is doing, except use Google Guava Lists.partition to get the sublists.
public void saveBatch(final List<Employee> employeeList) {
final int batchSize = 500;
List<List<Employee>> batchLists = Lists.partition(employeeList, batchSize);
for(List<Employee> batch : batchLists) {
getJdbcTemplate().batchUpdate(QUERY_SAVE, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
Employee employee = batch.get(i);
ps.setString(1, employee.getFirstname());
ps.setString(2, employee.getLastname());
ps.setString(3, employee.getEmployeeIdOnSourceSystem());
}
#Override
public int getBatchSize() {
return batch.size();
}
});
}
}

Spring provides Batch operations with multiple batches. In the example below, the batch size is 100.
public class JdbcActorDao implements ActorDao {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public int[][] batchUpdate(final Collection<Actor> actors) {
int[][] updateCounts = jdbcTemplate.batchUpdate(
"update t_actor set first_name = ?, last_name = ? where id = ?",
actors,
100,
new ParameterizedPreparedStatementSetter<Actor>() {
public void setValues(PreparedStatement ps, Actor argument) throws SQLException {
ps.setString(1, argument.getFirstName());
ps.setString(2, argument.getLastName());
ps.setLong(3, argument.getId().longValue());
}
});
return updateCounts;
}
// ... additional methods
}

Still simplified way is modifying getBatchsize() method as in below works well
No need of partitioning or subset of list :),
#Override
public void saveBatch(final List<Employee> employeeList) {
final int batchSize = 500;
getJdbcTemplate().batchUpdate(QUERY_SAVE,
new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
Employee employee = employeeList.get(i);
ps.setString(1, employee.getFirstname());
ps.setString(2, employee.getLastname());
ps.setString(3, employee.getEmployeeIdOnSourceSystem());
}
#Override
public int getBatchSize() {
if (batchSize > employeeList.size()) {
return employeeList.size();
}
return batchSize;
}
});
}

Related

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

JavaFX - Incompatible parameter type with using TreeView.EditEvent in lambda

In a JavaFX TreeView I'm using 'custom' classes which extend TreeItem. This makes me able to edit the items in the TreeView (I can double click them and edit the contents when running the application) but I can't seem to be able to set the .setOnEditCommit() method properly. I was hoping it'd work similar as the function in a tableview but I didn't have any luck yet.
This is my code in my controller in which I try to set the setOnEditCommit() method. In my TreeView called 'trvDivisies' I display football team divisions / competitions and one level lower I display all the teams that are in a certain division.
private void setUpTreeView() {
trvDivisies.setEditable(true);
trvDivisies.setShowRoot(false);
TreeItem<String> root = new TreeItem<>();
for (Divisie d : divisies) {
TreeItem<String> divisieTreeItem = d;
divisieTreeItem.valueProperty().set(d.getNaam());
for (VoetbalTeam vt : d.getVoetbalTeams()) {
TreeItem<String> voetbalTeamTreeItem = vt;
voetbalTeamTreeItem.valueProperty().setValue(vt.getTeamNaam());
divisieTreeItem.getChildren().add(voetbalTeamTreeItem);
}
root.getChildren().add(divisieTreeItem);
}
trvDivisies.setRoot(root);
trvDivisies.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
System.out.println(newValue);
}
});
trvDivisies.setCellFactory(TextFieldTreeCell.forTreeView());
// I get an error at the following line when compiling
trvDivisies.setOnEditCommit((TreeView.EditEvent p) -> {
TreeItem<String> selectedItem = p.getTreeItem();
if (selectedItem instanceof Divisie) {
updateDivisie((Divisie)selectedItem);
} else if (selectedItem instanceof VoetbalTeam) {
updateTeam((VoetbalTeam)selectedItem);
}
});
}
This is what my 'custom' classes look like.
public class Divisie extends TreeItem<String> {
private static int idCount = 0;
private int id;
private String naam;
private List<VoetbalTeam> voetbalTeams;
public int getId() {
return id;
}
public String getNaam() {
return naam;
}
public List<VoetbalTeam> getVoetbalTeams() {
return voetbalTeams;
}
public Divisie(int id, String naam) {
super(naam);
this.id = id;
this.naam = naam;
}
public Divisie(String naam) {
this.id = ++idCount;
this.naam = naam;
}
public void addTeam(VoetbalTeam toBeAdded) {
if (voetbalTeams == null) {
voetbalTeams = new LinkedList<>();
}
voetbalTeams.add(toBeAdded);
}
#Override
public String toString() {
return this.naam;
}
}
Second 'lower level' class
public class VoetbalTeam extends TreeItem<String> {
private static int idCount = 0;
private int id;
private String teamNaam;
private List<Speler> spelers;
public int getId() {
return id;
}
public String getTeamNaam() {
return teamNaam;
}
public List<Speler> getSpelers() {
return this.spelers;
}
public VoetbalTeam(int id, String teamNaam) {
super(teamNaam);
this.id = id;
this.teamNaam = teamNaam;
}
public VoetbalTeam(String teamNaam) {
super(teamNaam);
this.id = ++idCount;
this.teamNaam = teamNaam;
}
public void addSpeler(Speler nieuweSpeler) {
if (spelers == null) {
spelers = new LinkedList<>();
}
this.spelers.add(nieuweSpeler);
}
#Override
public String toString() {
return this.teamNaam;
}
}
When trying to run the application WITH the .setOnEditCommit() method I get an error saying:
Error:(97, 37) java: incompatible types: incompatible parameter types in lambda expression
I was hoping you guys can tell me what I need to change my TreeView.EditEvent lambda to or help me find an easier solution.
For a TreeView<T>, the signature of setOnEditCommit is
void setOnEditCommit(EventHandler<TreeView.EditEvent<T>> value)
Since you have (apparently) a TreeView<String>, you need
trvDivisies.setOnEditCommit((TreeView.EditEvent<String> p) -> {
// ...
});
Or, of course, you can just let the compiler do the work for you:
trvDivisies.setOnEditCommit(p -> {
// ...
});

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.

show GPS location on google map

I want to show the GPS location of the user on google maps by retrieving the longitude and latitude from SQLite. Please tell me the procedure to show the information from SQLite on Google map. Here is the code I am using for saving the longitude and latitude. And I am also using the link
http://www.androidhive.info/2012/01/android-working-with-google-maps/
for maps but don't know how to retrieve the longitude and latitude from SQLite.
MAiN ACTIVITY:
public class MainActivity extends Activity {
ListView list;
mylocation loc = new mylocation();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocationManager mylocman = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener myloclist = new mylocation();
mylocman.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,myloclist);
loc.updateDatabase(this);
GPSdatabase myDatabase=new GPSdatabase(this);
myDatabase.open();
Cursor cursor=myDatabase.getAllRows();
cursor.moveToFirst();
ArrayList listContents = new ArrayList();
for (int i = 0; i < cursor.getCount(); i++)
{
listContents.add("Lat=" +cursor.getString(1) +" "+"Log "+ cursor.getString(2));
cursor.moveToNext(); } myDatabase.close();
ListAdapter adapter=new ArrayAdapter(this,android.R.layout.simple_dropdown_item_1line, listContents);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
}
/*public void updateDatabase(){
GPSDatabase myDatabase=new GPSDatabase(context);
myDatabase.open();
myDatabase.insertRow(lat.substring(0,4),log.substring(0,4));
myDatabase.close();
}*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}}
My Location class:
public class mylocation implements LocationListener {
String lat=null;
String log=null;
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
String text="my latitude="+location.getLatitude()+"longitude="+location.getLongitude();
lat=location.getLatitude()+"";
log=location.getLongitude()+"";
//updateDatabase();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void updateDatabase(Context context)
{
if(lat!=null || log!=null)
{
GPSdatabase myDatabase=new GPSdatabase(context);
myDatabase.open();
myDatabase.insertRows(lat.substring(0,4),log.substring(0,4));
myDatabase.close();
}
}
}
My DATABASE CLASS:
public class GPSdatabase {
private Context context;
private DbHelper dbHelper;
public final String DBNAME = "gps1";
public final int DBVERSION = 3;
public SQLiteDatabase db;
public final String COLUMN2 = "latitude";
public final String COLUMN3 = "longitude";
public final String COLUMN1 = "locationId";
public final String TABLENAME = "location";
public final String CREATERDB = "create table location(locationId integer primary key autoincrement, latitude text not null, longitude text not null);";
public GPSdatabase(Context context) {
this.context = context;
dbHelper = new DbHelper(context);
}
public class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String CREATE_TABLE = "CREATE TABLE " + "location" + "(" +
"latitude" + " TEXT," +
"longitude" + " TEXT)";
db.execSQL(CREATE_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public long insertRows(String column2, String column3) {
ContentValues value = new ContentValues();
value.put(COLUMN2, column2);
value.put(COLUMN3, column3);
return db.insert(TABLENAME, null, value);
}
public Cursor getAllRows() {
Cursor cursor = db.query(TABLENAME, new String[] {
COLUMN1,
COLUMN2,
COLUMN3
}, null, null, null, null, null);
return cursor;
}
public void open() throws SQLException {
db = dbHelper.getWritableDatabase();
//return true;
}
public void close() {
dbHelper.close();
//return true;
}
}
Why not showing directly the location of the user without saving and retrieving back and forth?
if you tell to the map to show user location, it is done automatically:
http://developer.android.com/reference/com/google/android/gms/maps/GoogleMap.html#setMyLocationEnabled(boolean)
map.setMyLocationEnabled(true);

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