Sqlite database to change TextView in android app - android

I am setting my textview using columns from a sqlite database file.Problem is that when i change the view back and forth, there is a very obvious lag while it retrieves from the database.Here is the code:
public class Flipcard extends Activity implements OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout layMain = (LinearLayout) findViewById(R.id.FlashCardFront);
layMain.setOnClickListener(this);
Cursor cur;
DbH db = null;
TextView tv=(TextView) findViewById(R.id.TV_Word);
TextView txtView=(TextView) findViewById(R.id.TV_CardNo);
try {
db=new DbH(this);
} catch (IOException e2) {
e2.printStackTrace();
}
try {
db.createdatabase();
} catch (IOException e) {
e.printStackTrace();
}
db.opendatabase();
cur=db.data();
cur.moveToFirst();
tv.setText(cur.getString(0));
cur.close();
}
public void onClick(View v) {
Intent i=new Intent(this,Flipcard_back.class);
startActivity(i);
}
}
the other java file that is being called on click is:
public class Flipcard_back extends Activity implements OnClickListener{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_back);
LinearLayout layMain = (LinearLayout) findViewById(R.id.FlashCardRear);
layMain.setOnClickListener(this);
}
public void onClick(View v) {
Intent i=new Intent(this,Flipcard.class);
startActivity(i);
}
}
which is actually calling previous one.The problem is i'm one a very initial phase on my app development.Right now i am only trying to change two textviews in first java file using my database.When i switch back and forth there is a lag of around a second.How do i correct it? am i doing something wrong.
Also i am not able to retrieve all the rows using getstring(1) etc.Why so?How do i get the columns one by one?

The lag is caused by accessing your database in your main thread, you want to have it run in its own thread. Here is a the Developer's Guide on Processes and Thread which will give you the grand overview. Look into something like AsyncTask next, for one approach to accessing databases.
As for not getting results from your database, I cannot tell without seeing the class associated with db. Include that code and any logcat errors in your question if you want more help.
EDIT
With the error code you provided I found this link to a similar question and detailed answer.

My experience from sqlite + android is that its initially very slow when quering the database, but after that it can retrieve large amounts of data very fast. If you want to avoid lag, use a file instead.
My tiny experience comes from developing the dictionary app Wordlist Pro where I had to abandon the database for textfiles since it was way too slow (and big in size).

Related

How to simulate an user click to a listview item in junit testing?

I am try to write a junit test case on selecting a list item and intent to next activity, but i dont know how to simulate this user action by junit coding. Can anyone help?
Also i wanna ask, is there any material teaching the function or syntax on simlate different user action in junit?
The following is a example from my school tutorial notes, and i want to do something like this one, but on a listview item.
public void testKilosToPounds() {
/* INTERACTIONS */
TouchUtils.tapView(this, textKilos); // tap the EditText textKilos
sendKeys("1"); // sent the number 1
TouchUtils.clickView(this, buttonPounds); // click the button buttonPounds
/*CHECK THE RESULT*/
double pounds;
try {
pounds = Double.parseDouble(textPounds.getText().toString());
} catch (NumberFormatException e) {
pounds = -1;
}
//JUnit Assert equals
// message expected actual delta for comparing doubles
assertEquals("1 kilo is 2.20462262 pounds", 2.20462262, pounds, DELTA);
}
I am working on JUnit from last few months to test android applications. And so i am now able to test almost things like webservices and views. Anyway i am sharing my code to test listview with item click and in next activity(InfoActivity) to check data that i sent using intent. InfoActivity is activity where i am sending data of clicked item from ListActivity.
public class ListActivityTest extends ActivityInstrumentationTestCase2<ListActivity> {
private Activity activity;
private ListView lv;
private InfoActivity contextInfoActivity;
private TextView tvInfo;
public ListActivityTest(){
super(ListActivity.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
activity = (ListActivity)getActivity();
lv = (ListView)activity.findViewById(R.id.lv);
}
public void testCase1(){
assertNotNull(activity);
assertNotNull(lv);
}
public void testCase2(){
Instrumentation instrumentation = getInstrumentation();
Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(InfoActivity.class.getName(), null, false);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
lv.performItemClick(lv,4,0);
//lv is listview,4 is item position,0 is default id
}
});
Activity currentActivity = getInstrumentation().waitForMonitor(monitor);
contextInfoActivity = (InfoActivity) currentActivity;
assertNotNull(contextInfoActivity);
tvInfo = (TextView)contextInfoActivity.findViewById(R.id.tvInfo);
assertNotNull(tvInfo);
assertEquals("Karan",tvInfo.getText().toString());
//karan is name at position 4 in listview and i am checking it with name set in textview of next activity i.e infoActivity.
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
activity = null;
lv = null;
tvInfo = null;
contextInfoActivity = null;
}
Hope this ll b helpfull for you.I you want to ask something feel free to ask.Thanks
You can click on a specific row in a ListView by first getting the View that holds that child, and then passing that view in to TouchUtils.clickView.
If you have a ListView view and ActivityInstrumentationTestCase2 this, and you want to click position p in the view:
TouchUtils.clickView(this, view.getChildAt(p));
You probably also want to check if the view is actually on screen too.

How to save multiple values to a single variable through an activity.

I am creating an application in which I scan a number of bar codes and keep extracting their values and clubbing them in a single place. As simple as this sounds I have been unable to create either an array in which I keep storing new values or a string where I keep concatenating them.
Please comment in case someone needs more code or explanation, I understand the question might not be very rich in either.
EDIT :
public class example
{
String val;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
try
{
String list_id=ToolList3.ID;
String list_qty=ToolScanDet3.qty;
// val is returned from the barcode scanning app.
val=val+issue_id+"~"+issue_qty+";";
Log.d("Tools issued till yet...", val);
/* Club all the tool IDs together and fire a single query to issue
them all against one name. */
Intent i=new Intent(Issue.this,Issue1.class);
startActivity(i);
//Issue1 again returns a pair of id and qty which needs to be saved along with the previous set of values.
}
I am basically having trouble trying to save the returned set of values along with the previous ones, the new ones that are returned wipe out the previous values. I tried putting them in an array too but that requires a counter which again defeats the purpose because the counter will be initialized to zero and start over again.
Unless the number of elements is known and constant, it is preferred to use ArrayList instead of array. In the case when you want to keep the data when the activity is destroyed caused by orientation change, you can save them in onSavedInstanceState :
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("temp", tempString);
}
Then retrieve it back in onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
your_arraylist = savedInstanceState.getString("temp");
}
EDIT:
According to what you want, the Scan activity should not initialize any string. It should obtain the string value which is passed to it by the main instead:
public class ScanActivity extends Activity {
String tempString;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState == null) {
tempString = getIntent().getStringExtra("temp");
} else {
// orientation change
tempString = saveInstanceState.getString("temp");
}
}
Once you have finished the scan, do
Intent output = new Intent();
output.putExtra("temp", tempString);
setResult(RESULT_OK, output);
finish();
to send back the string to your Main activity.
I could not find any solution that was feasible to my situation and thats why I had to create a local database using SQL Lite. Pushing values to the database each time needed and then retrieving the values after my work flow was over.
Comment in case anyone needs help with the creation of a local database using SQL Lite. Happy to help :)

How do I save the content view of my activity?

Alright so in my activity i changed my content view from one to another as you can see. so i was wondering how to save the content view that was there last when my activity was closed.
public class Levels extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
setContentView(R.layout.levels);
final EditText anstext1 = (EditText) findViewById(R.id.anstext1);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String result = anstext1.getText().toString();
if(result.equals("they"))
setContentView(R.layout.social);
else
Toast.makeText(getApplicationContext(), "Wrong", Toast.LENGTH_LONG).show();
}
});
}
}
setContentView
You should call this method only once in the Activity lifecycle.
Saving State
Most of the time you will save your models using onSaveInstanceState and restore them using the bundles generated from that method. Activity, Fragment and Views have these kind of methods build in.
Persisting state
If you are required to use the data for a longer period than the current app lifecycle you can use one of the following mechanisms:
SharedPreferences
SQL-lite DB
File I/O
Create a variable that has the type of R.layout.levels. Assuming R.layout.levels is a RelativeLayout: RelativeLayout rl;
Initialize it like this:
rl = (RelativeLayout) getLayoutInflater().inflate(R.layout.levels,null);
setContentView (rl);
If you want to save the variable for when the activity is destroyed you can put it in a custom Application class and retrieve it from there. You find here how to do it at "maintaining global state" : http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android
I don't know if it is good or bad to do this, but it could be a solution for what you're asking.

Exception when accessing SQLite database while switching between activities

My app consists of a number of activities, upto now I have had no problems with accessing the database when moving between the activities. However on the last listActivity (LocationActivity), I have an embedded button on each listView item.
When one of these buttons are clicked, it sends you to SpecificationEdit.java where the user inputs the specfication into some EditText fields for that listView item (a damaged component), but when you click Save it crashes with the following error message (note the data is saved to database ok):
java.lang.RuntimeException: Unable to resume activity blah blah
Exception: trying to requery an already closed cursor blah blah
Here is the listActivity class:
public class LocationActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
setLongClick();
rmDbHelper = new RMDbAdapter(this);
rmDbHelper.open();
getIntents();
setUpViews();
setAdapter();
setTextChangedListeners();
}
protected void onResume(){
super.onResume();
final Cursor locationCursor = (Cursor) rmDbHelper.fetchLocationsForRun(runId);
startManagingCursor(locationCursor);
locationCursorSize = locationCursor.getCount();
setAdapter();
setTextChangedListeners();
}
And here is the bit in this activity where is sends you to SpecificationEdit.java
private void startComponentEdit() {
Intent i = new Intent(LocationActivity.this, SpecificationEdit.class);
i.putExtra("Intent_InspectionID", inspectionId);
i.putExtra("Intent_AreaID", areaId);
i.putExtra("Intent_RunID", runId);
i.putExtra("Intent_LocationID", locationId);
i.putExtra("Intent_Ref", locationRef);
i.putExtra("Intent_DamagedComponentID", damagedComponentId);
startActivityForResult(i, ACTIVITY_CREATE);
}
And here is the OnCreate in SpecificationEdit.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rmDbHelper = new RMDbAdapter(this);
rmDbHelper.open();
Intent i = getIntent();
inspectionId = i.getLongExtra("Intent_InspectionID", -1);
areaId = i.getLongExtra("Intent_AreaID", -1);
runId = i.getLongExtra("Intent_RunID", -1);
locationId = i.getLongExtra("Intent_LocationID", -1);
damagedComponentId = i.getLongExtra("Intent_DamagedComponentID", -1);
setContentView(R.layout.edit_specification);
setUpViews();
populateFields();
fillSpinner();
setListeners();
}
With the bit of code which fires when you click the save button:
protected void saveDamagedComponentSpec() {
String manufacturer = ((Cursor)manufacturerSpinner.getSelectedItem()).getString(1).toString();
String text1 = specEditText1.getText().toString();
String text2 = specEditText2.getText().toString();
String text3 = specEditText3.getText().toString();
String text4 = specEditText4.getText().toString();
String notes_spec = specEditTextNotes.getText().toString();
rmDbHelper.saveDamagedComponentSpec(damagedComponentId, manufacturer, text1, text2, text3, text4, notes_spec);
if ("Yes".equals(specSaved)){
Toast.makeText(getApplicationContext(), "Component specification updated",
Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getApplicationContext(), "Component specification added",
Toast.LENGTH_SHORT).show();
}
finish();
}
Finally, here is the code in my database helper class:
//Constructor - takes the context to allow the database to be opened/created
public RMDbAdapter(Context ctx) {
this.mCtx = ctx;
}
/**
* Open the rm database. If it cannot be opened, try to create a new
* instance of the database. If it cannot be created, throw an exception to
* signal the failure
*
* #return this (self reference, allowing this to be chained in an
* Initialisation call)
* #throws SQLException if the database could be neither opened or created
*/
public RMDbAdapter open() throws SQLException {
rmDbHelper = new DatabaseHelper(mCtx);
rmDb = rmDbHelper.getWritableDatabase();
return this;
}
public void close() {
rmDbHelper.close();
}
The weird thing is, you can click on one of the listView item (the actual item not the embedded item) or the button 'add new component' and this will send you to another activity ComponentEdit.java with very similar interface (to add a component to the list) as SpecificationEdit but which when it finishes doesn't crash the app.
I can't see any major difference between the two activities, yet one is crashing with this error when you return to LocationActivity and one is not.
I have just tried removing onResume and this made no difference.. Hit a brick wall with this and it's driving me nuts.
I should add that it is working ok on my emulator, but crashes when I test it on my phone (HTC One S). Very strange..
Don't forget to call rmDbHelper.close(); before start another activity
Right, found the issue (spot the obvious mistake):
Cursor componentsCursor = (Cursor) rmDbHelper.fetchDamagedComponentSpecForInspection(inspectionId, componentType);
startManagingCursor(componentsCursor);
Intent i = new Intent(this, SpecificationEdit.class);
i.putExtra("Intent_InspectionID", inspectionId);
i.putExtra("Intent_AreaID", areaId);
i.putExtra("Intent_RunID", runId);
i.putExtra("Intent_LocationID", locationId);
i.putExtra("Intent_Ref", locationRef);
i.putExtra("Intent_DamagedComponentID", damagedComponentId);
startActivityForResult(i, ACTIVITY_CREATE);
componentsCursor.close();
So it wasn't this obvious (I had some blocked out code left in before the componentsCursor.close()), but when I finished SpecifcationEdit.class, I guess it returns to this activity and tries to close the componentsCursor but obviously fails.
Stupid thing is, I hadn't actually got this cursor doing anything yet! Doh!
Just for some additional advice/whittering; my app is fundimentally different to the Google notePad example, as I don't actually use the startActivityForResult as they do (in fact now I understand it better I will replace these all with just startActivity) as I input the data into the database while still on the edit activities, there and then (rather than passing this information through an intent then addinig when you return to the previous activity.
I find this more logical in the realms of my code, but any feedback on this approach?

android - pass data from one activity to a list in a second activity

new to droid programming. im having a small problem that im sure is simply fixed but ive done some searching and a bunch of tutorials but cant seem to find just what i need so i figured id ask. My app has 2 activites, the first activity is just a simple form where a user enters course information(class title, professor..etc.)
the first activity passes the data which is supposed to be stored in a list in the second activity. problem is that only the first course gets stored in the list, after the first time nothing new gets added to the second activity. Can someone point me in the right direction please? thanks in advance
First Activity
public class CourseDetail extends Activity {
//Course c = new Course();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button save=(Button)findViewById(R.id.save);
save.setOnClickListener(onSave);
}
private View.OnClickListener onSave=new View.OnClickListener() {
public void onClick(View v) {
EditText course=(EditText)findViewById(R.id.course);
EditText professor=(EditText)findViewById(R.id.professor);
EditText location=(EditText)findViewById(R.id.location);
EditText officehrs=(EditText)findViewById(R.id.officehrs);
Intent i=new Intent(CourseDetail.this, CourseList.class);
i.putExtra("myCourse", course.getText().toString());
i.putExtra("myProfessor", professor.getText().toString());
i.putExtra("myLocation", location.getText().toString());
i.putExtra("myOfficehrs", officehrs.getText().toString());
startActivity(i);
}
};
}
Second Activity
public class CourseList extends Activity {
Button btnCourse;
List<Course> model = new ArrayList<Course>();
CourseAdapter adapter=null;
private String dCourse="";
private String dProfessor="";
private String dLocation="";
private String dOfficehrs="";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.clist);
ListView list =(ListView)findViewById(R.id.courses);
adapter=new CourseAdapter();
list.setAdapter(adapter);
Course c = new Course();
Bundle extras = getIntent().getExtras();
dCourse = extras !=null ? extras.getString("myCourse") :"no value entered";
dProfessor = extras !=null ? extras.getString("myProfessor") :"no value entered";
dLocation = extras !=null ? extras.getString("myLocation") :"no value entered";
dOfficehrs = extras !=null ? extras.getString("myOfficehrs") :"no value entered";
c.setCourse(dCourse);
c.setProfessor(dProfessor);
c.setLocation(dLocation);
c.setOfficeHrs(dOfficehrs);
btnCourse =(Button)findViewById(R.id.btnCourse);
btnCourse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
}
You are just getting the user entered value in CourseDetail activity and displaying the received value inside the CourseList activity, that means you are not storing these values permanently.
Go through this Android - Data Storage document.
When you move to 2nd activity i.e. CourseList activity, at that time fetch the data from the SQLite table and display the same. whenever you get new values from previous activity, at that time just update the list by adding the new data in ArrayList and make a call on adapter.notifyDataSetChanged()
Some suggestions:
Have your CourseList extend ListActivity instead of just Activity - check out some tutorials on that which should help you set things up correctly.
There seems to be a bit of confusion with how you're handling your lists - you have your model variable but don't seem to be doing anything with it. Again, have a look at a ListView tutorial (just google "android listview tutorial").
You seem to have figured out that you can use "intents" to pass information from one activity to another, but since you're only doing this in the onCreate() method, it's only happening once. Try doing this in your ListActivity's adapter once for each item.
Don't give up on Android, keep trying :-)
Some suggestion:
You have to add your object to the adapter: adapter.add(c); after you get the data.
Call adapter.notifyDataSetChanged() to notify the system that your data for the listView has been changed. Call list.invalidate() to refresh it.
I noticed that you set the button with the finish() method. Hmm, if you do so, the next time you get to CourseList Activity from CourseDetail, the adapter will be null again. No previously received data will be available. Is this what you really want?
The problem is you are not adding the newly added items to the List.So before setting adapter you have to add all your objects like
list.add(c);

Categories

Resources