I am making an app in Android Studio and I am having some troubles with some methods, sorry if the code is bad, I am a CS student and making something like this for the first time.
Here is some code for the methods I already have
//this is my onCreate method, if you need it
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
oAPABD = new AjudanteParaAbrirBD(this);
oSQLiteDB = oAPABD.getWritableDatabase();
LinearLayout oLL = (LinearLayout)findViewById(R.id.llsv);
Cursor oCursor = oSQLiteDB.query(
oAPABD.TABLE_NAME,
new String[]{"*"},
null,
null,
null,
null,
null,
null);
boolean bCarryOn = oCursor.moveToFirst();
while (bCarryOn){
LinearLayout oLL1 = (LinearLayout)getLayoutInflater().inflate(R.layout.lines1,null);
oLL1.setId(oCursor.getInt(0)*10+8);
TextView oED1 = (TextView) oLL1.findViewById(R.id.ED1);
TextView oED2 = (TextView) oLL1.findViewById(R.id.ED2);
TextView oED3 = (TextView) oLL1.findViewById(R.id.ED3);
oED1.setId(oCursor.getInt(0)*10+2);
oED1.setText(oCursor.getInt(0)+"");
//COL 2 = ITENS
//DESCRIPTION OF COL2 ITEM LIST MISSING
oED2.setId(oCursor.getInt(0)*10+3);
oED2.setText(oCursor.getInt(2)+"");
oED3.setId(oCursor.getInt(0)*10+4); //repetido 10+4;
oED3.setText(oCursor.getString(3));
oLL.addView(oLL1);
bCarryOn = oCursor.moveToNext();
}
}
//INSERT NEW method
public void novoPedido(View v){
Intent intento1 = new Intent(Main2Activity.this, activityPedido.class );
intento1.putExtra("acao","novoPedido");
intento1.putExtra("count",(getLastID()+1)+"");
intento1.putExtra("currentTime",currentTime);
startActivityForResult(intento1, iRequest_Code1);
}
//EDIT method
public void editPedido(View v){
Intent intento2 = new Intent(Main2Activity.this, activityPedido.class );
intento2.putExtra("acao","editarPedido");
//not implemented
startActivityForResult(intento2,iRequest_Code2);
}
//DELETE method
public void deletePedido(View v){
//oSQLiteDB.delete(oAPABD.TABLE_NAME, "id = ?" + choosenRowID/10,null);
oSQLiteDB.execSQL("DELETE FROM " + oAPABD.TABLE_NAME + " WHERE " + oAPABD.COL1 + "=\"" + choosenRowID/10 + "\"");
oSQLiteDB.close();
LinearLayout oLL1 = (LinearLayout)findViewById(choosenRowID+8);
((LinearLayout) oLL1.getParent()).removeView(oLL1);
}
//decided to go with activityResult like this (only inser method included)
protected void onActivityResult(int iReqCode, int iResultCode, Intent iResult){
oAPABD = new AjudanteParaAbrirBD(this);
oSQLiteDB = oAPABD.getWritableDatabase();
if( (iReqCode == iRequest_Code1) && (iResultCode == RESULT_OK)){ //ADICIONAR
String id = iResult.getStringExtra("id");
String listaItens = iResult.getStringExtra("itens");
String mesa = iResult.getStringExtra("mesa");
String cliente = iResult.getStringExtra("cliente");
LastID = Integer.parseInt(id);
ContentValues oCV = new ContentValues();
oCV.put(oAPABD.COL1, id );
//oCV.put(oAPABD.COL2, listaItens);
oCV.put(oAPABD.COL3, mesa);
oCV.put(oAPABD.COL4, cliente);
oSQLiteDB.insert(oAPABD.TABLE_NAME,null,oCV);
//Toast.makeText(this, "Pedido adicionado com sucesso!", Toast.LENGTH_SHORT).show();
}else if((iReqCode == iRequest_Code2) && (iResultCode == RESULT_OK)){ //EDITAR
}else if((iReqCode == iRequest_Code3) && (iResultCode == RESULT_OK)){ //REMOVER
//Toast.makeText(this, "Pedido removido com sucesso!", Toast.LENGTH_SHORT).show();
}else{
//Toast.makeText(this, "Ups! Algo correu mal...", Toast.LENGTH_SHORT).show();
}
}
on my other activity, the one which I'm using for inserting and then it gives me the result back is defined like this:
public class activityPedido extends Activity {
AjudanteParaAbrirBD oAPABD;
SQLiteDatabase oSQLiteDB;
TextView tvAction;
EditText etInfo1,etInfo2,etInfo3,etCliente,etEmpregado,etPedido;
ImageButton bSaveNew,bSaveEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pedido);
Intent iCameFromAct2 = getIntent();
String action = iCameFromAct2.getStringExtra("acao");
String currentTime = iCameFromAct2.getStringExtra("currentTime");
tvAction = (TextView)findViewById(R.id.tAction);
etInfo1 = (EditText)findViewById(R.id.etInfo1);
bSaveNew = (ImageButton)findViewById(R.id.bSaveNew);
bSaveEdit = (ImageButton)findViewById(R.id.bSaveEdit);
etInfo3 = (EditText)findViewById(R.id.etInfo3);
etPedido = (EditText)findViewById(R.id.etPedido);
if (action.equals("novoPedido")){
tvAction.setText("Novo Pedido");
etInfo3.setText(currentTime);
bSaveEdit.setVisibility(View.GONE);
etInfo1.setText(iCameFromAct2.getStringExtra("count"));
etInfo1.setInputType(InputType.TYPE_NULL);
}
if (action.equals("editarPedido")){
tvAction.setText("Editar Pedido");
bSaveNew.setVisibility(View.GONE);
}
if (action.equals("removerPedido")){
tvAction.setText("Remover Pedido");
}
}//onCreate
/*Using this to make the "same button" with 2 different onClick methods:
saveNew(save data when clicked ADD NEW in the previous activity)
and saveEdit(bellow)
which I haven't yet done anything to it and is the one I really needed help,
because I can't figure out out to make it)*/
public void saveNew(View v){
etInfo1 = (EditText)findViewById(R.id.etInfo1);
etInfo2 = (EditText)findViewById(R.id.etInfo2);
etCliente = (EditText)findViewById(R.id.etCliente);
etPedido = (EditText)findViewById(R.id.etPedido);
Intent iResult = new Intent();
iResult.putExtra("id",etInfo1.getText().toString());
iResult.putExtra("mesa",etInfo2.getText().toString());
iResult.putExtra("cliente",etCliente.getText().toString());
iResult.putExtra("itens",etPedido.getText().toString());
setResult(RESULT_OK, iResult);
super.finish();
}
public void saveEdit(View v){
etInfo1 = (EditText)findViewById(R.id.etInfo1);
etInfo2 = (EditText)findViewById(R.id.etInfo2);
etCliente = (EditText)findViewById(R.id.etCliente);
etPedido = (EditText)findViewById(R.id.etPedido);
super.finish();
}
public void goBack(View v){
finish();
}
}
Adding the error in LogCat as asked in the comments:
2019-11-20 14:31:10.355 14923-14923/pmd.di.ubi.pedidunchos_2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: pmd.di.ubi.pedidunchos_2, PID: 14923
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.view.View$DeclaredOnClickListener.onClick(View.java:5652)
at android.view.View.performClick(View.java:6615)
at android.view.View.performClickInternal(View.java:6592)
at android.view.View.access$3100(View.java:786)
at android.view.View$PerformClick.run(View.java:25951)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6815)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.view.View$DeclaredOnClickListener.onClick(View.java:5647)
at android.view.View.performClick(View.java:6615)
at android.view.View.performClickInternal(View.java:6592)
at android.view.View.access$3100(View.java:786)
at android.view.View$PerformClick.run(View.java:25951)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6815)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewParent android.widget.LinearLayout.getParent()' on a null object reference
at pmd.di.ubi.pedidunchos_2.Main2Activity.deletePedido(Main2Activity.java:134)
at java.lang.reflect.Method.invoke(Native Method)
at android.view.View$DeclaredOnClickListener.onClick(View.java:5647)
at android.view.View.performClick(View.java:6615)
at android.view.View.performClickInternal(View.java:6592)
at android.view.View.access$3100(View.java:786)
at android.view.View$PerformClick.run(View.java:25951)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6815)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
2019-11-20 14:31:10.437 1371-1830/? E/InputDispatcher: channel '55262fd pmd.di.ubi.pedidunchos_2/pmd.di.ubi.pedidunchos_2.Main2Activity (server)' ~ Channel is unrecoverably broken and will be disposed!
2019-11-20 14:31:10.450 1371-1830/? E/InputDispatcher: channel 'c67c606 pmd.di.ubi.pedidunchos_2/pmd.di.ubi.pedidunchos_2.MainActivity (server)' ~
Channel is unrecoverably broken and will be disposed!
Delete method with error I want to make a method to delete a choosen row and update the view of the database table. The method I have, is only deleting it, but with erros. By errors I mean: whenever I click the row I want to delete and then click on the delete button, the app is restarts. And it actually deletes the row from the db.
The reason why the delete works but then crashes is that you are getting a null pointer exception (NPE) when trying to get the parent view of the calculated/rderived LinearLayout when using ((LinearLayout) oLL1.getParent()).removeView(oLL1);
So the row has been deleted.
If you put a breakpoint on the line ((LinearLayout) oLL1.getParent()).removeView(oLL1);
and run in debug mode and attempt a deletion then the debug window will appear and if you use that to inspect the variables you will probably see that oLL1 is null or if not if the you split ((LinearLayout) oLL1.getParent()).removeView(oLL1);
into 2 statements that the result of ((LinearLayout) oLL1.getParent()) is null.
If (my interpretation/assumption is that the onClicked view is a button in the list presented to the user, rather than a single button), as such to remove the row's view (assuming the Linear Layout is the parent of the clicked button) then you should be getting and removing the parent of the clicked button.
v
that is passed to the deletePedido
method.However, I believe that you are basically trying to re-invent the proverbial wheel and that matters would be greatly simplified if instead of trying to manage your own List of Views that you used a ListView or a RecyclerView as these manage the handling of the rows in the list of data.
The following is an example that allows you to insert, edit and delete rows from a table. Noting that insert is mimiced rather than calling another activity edit does nothing but includes comments - in short if you use the id (assuming that it an alias of the rowid)) all that you need to do is pass the id to the activity and it can then retrieve the entire row.
An attempt has been made to make the example similar to what has been assumed as the goal in you question.
First the main activities layout :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!">
</TextView>
<ListView
android:id="@+id/olv1"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="0dp">
</ListView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/insert"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="ADD NEW">
</Button>
<Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="DELETE SELECTED">
</Button>
<Button
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="EDIT SELECTED">
</Button>
</LinearLayout>
</LinearLayout>
The TextView current is used to display the currently selected row (clicking a row will selected that row).
The ListView takes a layout (see MainActivity where the stock SimpleListItem_2 layout has been used for each row). There are three buttons ADD NEW, EDIT SELECTED and DELETE SELECTED.
All of the Database Access mehods (queries, inserts, deletes and updates) are in the DatabaseHelper class AjudanteParaAbrirBB.java :-
public class AjudanteParaAbrirBD extends SQLiteOpenHelper {
public static final String DBNAME = "ajudante_para_abrir_BD";
public static final int DBVERSION = 1;
public static final String TABLE_NAME = "mytable";
public static final String COL_ID = BaseColumns._ID;
public static final String COL_ACAO = "acao";
public static final String COL_COUNT = "count";
public static final String COl_CURRENTTIME = "currentTime";
public AjudanteParaAbrirBD(Context context) {
super(context, DBNAME, null, DBVERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_table_sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"(" +
COL_ID + " INTEGER PRIMARY KEY, " +
COL_ACAO + " TEXT," +
COL_COUNT + " INTEGER, " +
COl_CURRENTTIME + " TEXT " +
")";
db.execSQL(crt_table_sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long insert(String acao, long count, String currentTime) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COL_ACAO,acao);
cv.put(COL_COUNT,count);
cv.put(COl_CURRENTTIME,currentTime);
return db.insert(TABLE_NAME,null,cv);
}
public int update(long id, String acao, long count, String currentTime) {
int rv = -1;
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
if (acao != null && acao.length() > 0) {
cv.put(COL_ACAO,acao);
}
if (count > -1) {
cv.put(COL_COUNT,count);
}
if (currentTime != null && currentTime.length() > 0) {
cv.put(COl_CURRENTTIME,currentTime);
}
if (cv.size() > 0) {
rv = db.update(
TABLE_NAME,cv,
COL_ID + "=?",
new String[]{String.valueOf(id)}
);
}
return rv;
}
public int delete(long id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(
TABLE_NAME,
COL_ID + "=?",
new String[]{String.valueOf(id)}
);
}
public Cursor getAll() {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(
TABLE_NAME,
null,
null,
null,
null,
null,
null
);
}
public String getCurrentSelection(long id) {
String rv = "Nothing to Select";
String derivedColumn = "dr";
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(TABLE_NAME,new String[]{
"'ACAO is '||" + COL_ACAO +
"||' Count='||" + COL_COUNT +
"||' CurrentTime='||" + COl_CURRENTTIME +
"||' ID='||" + COL_ID +
" AS " + derivedColumn},
COL_ID + "=?",new String[]{String.valueOf(id)},
null,null,null
);
if (csr.moveToFirst()) {
rv = csr.getString(csr.getColumnIndex(derivedColumn));
}
csr.close();
return rv;
}
}
Putting it all together is MainActicity.java :-
public class MainActivity extends AppCompatActivity {
ListView dblist;
TextView currentSelection;
Button add,edit,delete;
SimpleCursorAdapter adapter;
AjudanteParaAbrirBD DBHelper;
Cursor csr;
long current_id = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
currentSelection = this.findViewById(R.id.current);
dblist = this.findViewById(R.id.olv1);
add = this.findViewById(R.id.insert);
edit = this.findViewById(R.id.edit);
delete = this.findViewById(R.id.delete);
DBHelper = new AjudanteParaAbrirBD(this);
setupButtons();
manageListView();
}
@Override
protected void onResume() {
super.onResume();
manageListView(); //<<<<<<<<<< refreshes the ListView
}
private void manageListView() {
edit.setVisibility(View.INVISIBLE);
delete.setVisibility(View.INVISIBLE);
csr = DBHelper.getAll();
if (csr.getCount() > 0) {
if (csr.moveToFirst()) {
current_id = csr.getLong(csr.getColumnIndex(AjudanteParaAbrirBD.COL_ID));
currentSelection.setText(
DBHelper.getCurrentSelection(current_id)
);
csr.moveToPosition(-1);
}
edit.setVisibility(View.VISIBLE);
delete.setVisibility(View.VISIBLE);
}
if (adapter == null) {
adapter = new SimpleCursorAdapter(
this,
android.R.layout.simple_expandable_list_item_2,
csr,
new String[]{AjudanteParaAbrirBD.COL_ACAO, AjudanteParaAbrirBD.COl_CURRENTTIME},
new int[]{android.R.id.text1, android.R.id.text2},
0
);
dblist.setAdapter(adapter);
dblist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
current_id = id;
currentSelection.setText(DBHelper.getCurrentSelection(id));
}
});
} else {
adapter.swapCursor(csr);
}
}
private void setupButtons() {
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleInsertButtonClicked();
}
});
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleDeleteButtonClicked(current_id);
}
});
edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleEditButtonClicked(current_id);
}
});
}
private void handleInsertButtonClicked() {
//...... instantiate intent and startactivity to insert row
// HOWEVER for demo
DBHelper.insert("XX",99,"2019-01-01");
manageListView(); //<<<<<< note only needed because onResume is not called
// onResume would be called when the started activity is finished
}
private void handleEditButtonClicked(long id) {
//...... instantiate intent, add intent extra for id, and then startactivity to edit
}
private void handleDeleteButtonClicked(long id) {
// No need to start and activity just delete and refresh list
DBHelper.delete(id);
manageListView();
}
}
When first run there is no data and thus only the ADD NEW button is available, as per :-
Rather than write an insert activity clicking the ADD NEW button inserts a row (allbeit that the data is the same EXCEPT for the id). The first time the ADD NEW button is clicked the DELETE SELECTED and EDIT SELECTED buttons are visible. Additionally the TextView at the top displays the information for that row.
After clicking ADD NEW another three times then 4 rows are displayed :-
If a row is clicked (e.g. the second) then the data for that row is displayed at the top. Noting that the id changes.
If say the 2nd row is clicked and then the DELETE SELECTED buttons is clicked then the row is deleted from the database and the ListView shows just the 3 remaining rows.
e.g.
Clicking Edit does nothing. However, the comments in the code indicate how to manage editing and inserting via activities.