J Huang J Huang - 27 days ago 7
Android Question

SQlite dataabase operation and AsyncTask

I am learning AsyncTask class and with following example to practice. I have a UI that have a EditText (for data entry), a radiogroup with 5 radiobuttons, and a button (submit). The idea is that when user select the radiobutton and enter a value to EDITTEXT. Following button click, the information will go to the database table. The database table is created and the whole code works. But I would like to run the database operation function in the background with AsyncTask. something goes wrong after applying AsyncTask class. Please help me.

here is the code works without AsyncTask:

package jhapps.com.myspending;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

public class Child extends AppCompatActivity {

private static Button btnsubmit;
private static RadioGroup rgChild;
private static RadioButton rbChild;
private static EditText dollarAmount;



@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_child);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DataSubmitChild();
}

private void DataSubmitChild(){
btnsubmit=(Button)findViewById(R.id.btnSubmitChild);
btnsubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
rgChild = (RadioGroup) findViewById(R.id.rgChildren);
int selectedRbChild = rgChild.getCheckedRadioButtonId();
rbChild = (RadioButton) findViewById(selectedRbChild);
String rbChildF = rbChild.getText().toString();



dollarAmount = (EditText) findViewById(R.id.amountEnterChild);
String dollarAmountF = dollarAmount.getText().toString();
float dollarAmountFloat = Float.parseFloat(dollarAmountF);





DataBaseHelper dataBaseHelper = new DataBaseHelper(Child.this);

if (dollarAmountFloat != 0 & rbChildF != "") {
int itemID;

switch (rbChildF) {
case "Daycare":itemID=53;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "Lessons and Activities": itemID=54;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "Allowance":itemID=55;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "School Supplies and Fees" :itemID=56;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "Babysitting":itemID=57;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;

}
Toast.makeText(Child.this,"Your spending is recorded!",Toast.LENGTH_LONG).show();

dollarAmount.setText("");
rgChild.clearCheck();
}else
Toast.makeText(Child.this,"Please choose an Item",Toast.LENGTH_LONG).show();
}

});


}

}


here is the code with AsyncTask that did not work:

package jhapps.com.myspending;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

public class Child extends AppCompatActivity {
private static Button btnsubmit;
private static RadioGroup rgChild;
private static RadioButton rbChild;
private EditText dollarAmount;

Context ctx;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_child);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
//DataSubmitChild();
rgChild = (RadioGroup) findViewById(R.id.rgChildren);
int selectedRbChild = rgChild.getCheckedRadioButtonId();
rbChild = (RadioButton) findViewById(selectedRbChild);

dollarAmount = (EditText) findViewById(R.id.amountEnterChild);



btnsubmit=(Button)findViewById(R.id.btnSubmitChild);
btnsubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
BackgroundTask backgroundTask=new BackgroundTask();
backgroundTask.execute();
}
});
dollarAmount.setText("");
rgChild.clearCheck();
}
private class BackgroundTask extends AsyncTask<Void,Void,Void>{
String rbChildF = rbChild.getText().toString();
String dollarAmountF = dollarAmount.getText().toString();
float dollarAmountFloat = Float.parseFloat(dollarAmountF);

@Override
protected Void doInBackground(Void... params) {


DataBaseHelper dataBaseHelper = new DataBaseHelper(getBaseContext());

if (dollarAmountFloat != 0 & rbChildF != "") {
int itemID;

switch (rbChildF) {
case "Daycare":itemID=53;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "Lessons and Activities": itemID=54;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "Allowance":itemID=55;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "School Supplies and Fees" :itemID=56;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;
case "Babysitting":itemID=57;
dataBaseHelper.insertDataSpending(itemID, dollarAmountFloat);
break;

}
Toast.makeText(Child.this,"Your spending is recorded!",Toast.LENGTH_LONG).show();


}else
Toast.makeText(Child.this,"Please choose an Item",Toast.LENGTH_LONG).show();

return null;
}


}
}

here is the error message:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: jhapps.com.myspending, PID: 27613
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.RadioButton.getText()' on a null object reference
at jhapps.com.myspending.Child$BackgroundTask.<init>(Child.java:62)
at jhapps.com.myspending.Child$BackgroundTask.<init>(Child.java:0)
at jhapps.com.myspending.Child$2.onClick(Child.java:54)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Answer

These views are all null...

private class BackgroundTask extends AsyncTask<Void,Void,Void>{

    // Don't put these here...
    String rbChildF = rbChild.getText().toString();
    String dollarAmountF = dollarAmount.getText().toString();
    float dollarAmountFloat = Float.parseFloat(dollarAmountF);

If you really need those values, then make a constructor

private class BackgroundTask extends AsyncTask<Void,Void,Void>{

    String rbChildF, dollarAmountF;
    float dollarAmount;

    public BackgroundTask(String radio, String dollarAmtF, float dollars) {
        this.rbChildF = radio;
        this.dollarAmountF = dollarAmtF;
        this.dollarAmount = dollars;
    }

And pass those values in

    String rbChildF = rbChild.getText().toString();
    String dollarAmountF = dollarAmount.getText().toString();
    float dollarAmountFloat = Float.parseFloat(dollarAmountF);

    new BackgroundTask(rbChildF, dollarAmountF, dollarAmountFloat).execute();