I'm trying to get a simple note-taking app to work, but I keep on getting a nullPointerException when calling a certain method.
The value from the textEdit in the dialog layout is retrieved just fine.
I checked by logging the results.
The problem occurs when I try to run the createNotes(content) method.
public class Dialog extends Activity {
NotesBean notesBean = null;
public NotesDao datasource;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("log", "Running NotiMgr");
setContentView(R.layout.dialog);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.dialog_background);
layout.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText mEdit = (EditText) v.findViewById(R.id.editText);
String content = mEdit.getText().toString();
Log.v("EditText", content);
//THIS IS WHERE THE ERROR OCCURS
datasource.createNotes(content);
finish();
}
});
}
This class deals with inserts, deletes and db related stuff. I've tried debugging, but it never reaches this class.
public class NotesDao {
public NotesBean createNotes(String content) {
try {
Log.v("createNotes", content);
ContentValues values = new ContentValues();
values.put(DbHelper.COLUMN_CONTENT, content);
long insertSeq = database.insert(DbHelper.TABLE_NOTES, null, values);
Cursor cursor = database.query(
DbHelper.TABLE_NOTES, //String table
allColumns, //String[] columns
DbHelper.COLUMN_SEQ + " = " + insertSeq, //String selection
null, //String[] selectionArgs
null, //String groupBy
null, //String having
null); //String orderBy
cursor.moveToFirst();
NotesBean newNotes = cursorToNotes(cursor);
cursor.close();
return newNotes;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
btw I have also confirmed that the db is opened through logcat...
But it was in a different activity. Does that mean I should close it and open it again in this activity?
Any help would be greatly appreciated! Thanks!
change:
public NotesDao datasource;
to
public NotesDao datasource=new NotesDao();
You have never initialized datasource until you call createNotes(), so the NullPointerException does not come unexpected.
You might consider making NotesDao a Singleton, if you don't need multiple instances of it. Just google Singleton.
you have never initialized 'datasource' object that is why it is giving null pointer exception.
NullPointer Exceptions always come up with missing initializations or wrong view element initialization. In your case you are missing to initialise datasource object (as pointed by earlier answers).
A valuable advice will be always cross check your program for everything is initialised, you may also use Exception Handling for cases you are not sure, like for data coming from different source.
You are not instantiate your NoteDao object. please update your code like this:
public NotesDao datasource=new NotesDao();
As stated, your other class is not initialized.
In your onCreate put the initialization.
datasource = new NotesDao();
You have to wait until your class is made in onCreate to initialize the variables in that class.
Related
I have an android app that is retrieving data from a mysql db via php.
It works fine, but i have a (simple) variable problem.
I want to create a variable inside MainActivity class.
Then inside MainActiviy class i have onCreate method - and inside that I have some json stuff that retrieves my data from mysql.
I now want to assign some mysql value to the variable i created in MainActivity class (it is assigned inside onResponse method from the json stuff), and then I simply want to use that variable and write it out on a textview, and I will do that in the bottom of the onCreate method.
But for some reason, it "forgets" the value I assigned to the variable, when I have to use it outside the onResponse method.
(if i set the textview text inside the onResponse method, it works fine).
public class MainActivity extends ActionBarActivity {
// I create the variable here
String someString;
TextView text;
RequestQueue reqq;
String showUrl = "http://www.someurl.com/get_data.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.textid);
reqq = Volley.newRequestQueue(getApplicationContext());
JsonObjectRequest jsonob = new JsonObjectRequest(Request.Method.POST,
showUrl, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray dataAr = response.getJSONArray("json_data");
for (int i = 0; i < dataAr.length(); i++) {
JSONObject dat = dataAr.getJSONObject(i);
// Here I want to assign some data from my mysql db to the variable
someString = dat.getString("aar");
// If I set the the textview to display value of someString HERE, it works!
// text.setText(someString);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error.getMessage());
}
});
reqq.add(jsonob);
// HERE i want to display the value of the variable in the textview!
// - but it doesnt "remember" the value
text.setText(someString);
}
}
If I use static keyword on the someString variable, it remembers the value, but only the SECOND time i open the app!
I'm very new at this, and have tried google, and tried some stuff with a singleton class, but I just don't seem to understand this!
I would love it, if someone could link me some information to help me get this, AND give an example of how my code should be, so it will work!
THANKS! :D
This behavior is due to the fact that
text.setText(someString);
is executed immediately in the onCreate method, & by immediately I mean that it does not wait for any response from the Volley request (the Volley request that you set up before). In other words, you need to wait till you get a response before you set the text on to your TextView.
That's why it successfully sets your TextView's text from within the onResponse method.
So I've debugged my program and have found that the part of my program is updating, whilst another isn't.
I have a method:
public void storeApplication(String name, String item){
Application app = new Application(name, item);
peopleAttending.add(app);
}
The debugger reports that an object is contained in the LinkedList (peopleAttending).
In another method:
public void populateListView() {
int noOfPeopleAttending = peopleAttending.size();
String noPeopleAttending = String.valueOf(noOfPeopleAttending);
Toast.makeText(GuestsAttending.this, noPeopleAttending, Toast.LENGTH_SHORT).show();
}
This method can be called after the previous one and states that there isn't an object within the LinkedList.
I've checked the object references just to make sure that they are pointing at the same reference and they are.
Any help would be greatly appreciated.
EDIT: Entire Class:
public class GuestsAttending extends Activity {
private LinkedList<Application> peopleAttending = new LinkedList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guests_attending);
populateListView();
}
public void storeApplication(String name, String item){
Application app = new Application(name, item);
peopleAttending.add(app);
}
public void populateListView() {
// GuestsAdapter adapter = new GuestsAdapter(this, peopleAttending);
// ListView listView = (ListView) findViewById(R.id.listView);
// listView.setAdapter(adapter);
peopleAttending.size();
int noOfPeopleAttending = peopleAttending.size();
String noPeopleAttending = String.valueOf(noOfPeopleAttending);
Toast.makeText(GuestsAttending.this, noPeopleAttending, Toast.LENGTH_SHORT).show();
}
Second Edit:
Java Booking Screen Method:
public void saveBookingInfo(View view) {
GuestsAttending sendApplication = new GuestsAttending();
EditText applicantNameText = (EditText) findViewById(R.id.applicantNameTextField);
EditText itemToBurnText = (EditText) findViewById(R.id.itemToBurnTextField);
String appName = applicantNameText.getText().toString();
String appItemToBurn = itemToBurnText.getText().toString();
if (appItemToBurn.isEmpty() || appName.isEmpty()) {
Toast.makeText(BookingScreen.this, "Please fill in all fields.", Toast.LENGTH_SHORT).show();
}
else {
sendApplication.storeApplication(appName, appItemToBurn);
}
}
GuestsAttending Java Class: -- See Above.
Useful hint: It's really popular to set type of List as a List<> interface from java.util package instead of LinkedList<> itself.
Anyway, i am pretty sure that storeApplication method is not automatically triggered before onCreate method ran by Activity framework. Maybe your debugger is stopoing on it in different order (because of using threads or smth), but you should to log some invoke. Try to find it out.
I've found out what the problem is:
When I submit the booking information, it runs all the necessary methods. However, when the "storeApplication()" method has finished executing, the ArrayList 'empties' all the objects out.
I only noticed this when I used breakpoint and tried running the method twice, on the second time I entered booking details, the ArrayList stated it was empty.
I'm going to see if I can try and store the ArrayList in a more secure place.
I'm trying to pass a TextView as a parameter to an external class to perform some functionality but I'm hitting a NullPointerException each time.
Activity.java
tv = (TextView) findViewById(R.id.tv);
Log.v("", "Contents: " + tv.getText().toString()); // This works fine
externalClass.addViewToList(tv);
externalClass.printViewContents(tv.getText().toString());
External Class
public List<View> _views;
// This doesn't work
public void addViewToList(View v) {
try {
this._views.add(v);
Log.v("", "Added " + v.getId() + " to list");
}
catch(NullPointerException ex) {
Log.e("", "NullPointerException when adding view to list");
}
}
// But this works fine
public void printViewContents(String contents) {
Log.v("",contents);
}
So I know the view has been found in the layout.xml and it has been initialized, my question is how do I pass a View from my Activity to an external class.
Thanks
Edit
Forgot that Lists need to be initalised as ArrayList
Cheers!
your _views list isnt initialized i.e youre trying to write data to null.
to solve this you need to write:
public List<View> _views = new List<>();
instead of just:
public List<View> _views;
for less headache I recommend that you work with an array list instead:
public ArrayList<View> list = new ArrayList<>();
now it will work :)
Your " _views" list did not initialized. see below it work.
public List _views = new ArrayList();
Thank you.
My application give me this warning
A SQLiteConnection object for database
'+data+data+com_example_test+database' was leaked! Please fix
your application to end transactions in progress properly and to close
the database when it is no longer needed.
But I close the db object and the cursor after every use.
try {
while (cursor.moveToNext()) {
...
}
} finally {
if (cursor != null && !cursor.isClosed())
cursor.close();
}
...
db.close();
Can you help me for understand what is the problem?
thanks!!!
UPDATE!
I try this solution from this post
SQLite Connection leaked although everything closed
and I don't have memory leak anymore, is it a good solution?
Possible Solutions:
You have not committed the transactions you have started (You should
always close the transaction once you started)
Check whether you have closed the cursors you have opened if you are
using Sqlite (Looks like you have done this step from the code you posted)
Also move the db.close to finally block
You have not called db.close on a database before deleting it with context.deleteDatabase(...) and then recreating it with dbHelper.getWritableDatabase()
Just drag that db.close up into the finally block.
//Inside your SQLite helper class
#Override
public synchronized void close () {
if (db != null) {
db.close();
super.close();
}
}
//Inside the activity that makes a connection to the helper class
#Override
protected void onDestroy () {
super.onDestroy();
//call close() of the helper class
dbHelper.close();
}
this code stops the leak and fixes cursor problems.
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static DatabaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
In my case the error was caused when y try to download new data and database should be updated.
I solved it instantiating the database by calling a SELECT 0. That cause database to be updated, so after that I try to download the new data. And worked fine.
Probably you forgot to remove the break point of debugging
sample:
In my case, I was calling to getWritableDatabase or getReadableDatabase and not use it at all. for example if you use it with "execSQL" execSQL will call "releaseReference" "Releases a reference to the object, closing the object if the last reference was released."
So I have a bit of a problem. I am trying to make my app do things based on the message it receives through GCM. In this case it's supposed to make a sound by using the TextToSpeech class. It kind of works, but not the first time I send the message. I realise this is probably because TextToSpeech hasn't been instantiated, but I'm not sure how go to about and do that? I tried onInit(), but that didn't work at all.
Also, what is the best way to shut down TTS in my example?
Disclaimer: I come from a PHP background, and know very little Java. I try to learn by doing, so please forgive me if this is a silly question. Thanks in advance!
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
public static TextToSpeech mtts;
public GCMIntentService() {
super(SENDER_ID);
}
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("message");
mtts = new TextToSpeech(context, null);
if (message.startsWith("makeSound")) {
mtts = new TextToSpeech(context, null);
mtts.setLanguage(Locale.US);
mtts.speak(message, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
It doesn't work the first time because the initialization of TextToSpeech is asynchronous. You can not simple instantiate it and use it as you are doing. You should provide a callback to be called once the TextToSpeech has been initialized if you want to use it right away.
mTextToSpeech = new TextToSpeech( this, new TextToSpeech.OnInitListener()
{
#Override
public void onInit( int status )
{
// Check for status might not be initialized due to errors
// Configure language/speed
}
} );
It does work the rest of the times, because mtts is static. This means that is a class variable and is not destroyed/initialized when creating new instances of the service. By the second time you use this service, this variable was already initialized in the first service execution.