I have a project that I'm developing in Android Studio where I use a Custom Adapter, an Employee, and a DatabaseHelper.
What happens, I use an already populated database that is in the Assets folder, which is copied to the application's Databases directory at startup.
I also have a layout where you have a field to search. When doing the search the user clicks a button and the Custom Adapter comes into action to popular the ListView.
In the ListView there is an ImageButtom where I'm trying to implement a routine where the user clicks on it so that the item in the list can be saved as a favorite. How was he doing this? by taking the sub sub-category number and the fav favorite value and passing it to the public void update (String sub, String fav) function in DatabaseHelper .
I was not able to implement the ImageButtom click, the only place I could do this was in the custom adapter.
I just can not get the data in the table to get the update, because when I click on ImageButtom the application stops working.
DatabaseHelper.java
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class DatabaseHelper extends SQLiteOpenHelper {
private final static String TAG = "Database";
private final Context myContext;
private static final String DATABASE_NAME = "my_db.db";
public static final String SUBCATEGORIA = "sub_categ";
public static final String FAV = "fav";
private static final int DATABASE_VERSION = 2;
private String pathToSaveDBFile;
public DatabaseHelper(Context context, String filePath) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
pathToSaveDBFile = new StringBuffer(filePath).append("/").append(DATABASE_NAME).toString();
}
public void prepareDatabase() throws IOException {
boolean dbExist = checkDataBase();
if(dbExist) {
int currentDBVersion = getVersionId();
if (DATABASE_VERSION > currentDBVersion) {
deleteDb();
try {
copyDataBase();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
} else {
try {
copyDataBase();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
}
private boolean checkDataBase() {
boolean checkDB = false;
try {
File file = new File(pathToSaveDBFile);
checkDB = file.exists();
} catch(SQLiteException e) {
Log.d(TAG, e.getMessage());
}
return checkDB;
}
private void copyDataBase() throws IOException {
OutputStream os = new FileOutputStream(pathToSaveDBFile);
InputStream is = myContext.getAssets().open(DATABASE_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
is.close();
os.flush();
os.close();
}
public void deleteDb() {
File file = new File(pathToSaveDBFile);
if(file.exists()) {
file.delete();
}
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public List<Employee> getEmployees(String codigo) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(pathToSaveDBFile, null, SQLiteDatabase.OPEN_READONLY);
String query = "SELECT sub_categ, descricao, descrabrev, fav FROM tab_mytabe WHERE TRIM(sub_categ) LIKE '%"+codigo+"%' OR TRIM(descricao) LIKE '%"+codigo+"%'";
Cursor cursor = db.rawQuery(query, null);
List<Employee> list = new ArrayList<>();
while(cursor.moveToNext()) {
Employee employee = new Employee();
employee.setSubcategoria(cursor.getString(0));
employee.setDescricao(cursor.getString(1));
employee.setDescrabrev(cursor.getString(2));
employee.setFavorito(cursor.getString(3));
list.add(employee);
}
db.close();
return list;
}
private int getVersionId() {
SQLiteDatabase db = SQLiteDatabase.openDatabase(pathToSaveDBFile, null, SQLiteDatabase.OPEN_READONLY);
String query = "SELECT versao FROM tab_versao";
Cursor cursor = db.rawQuery(query, null);
cursor.moveToFirst();
int v = cursor.getInt(0);
db.close();
return v;
}
}
CustomAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomAdapter extends ArrayAdapter<Employee> implements View.OnClickListener{
Animation animText;
String sub;
String fav;
private ArrayList<Employee> dataSet;
Context mContext;
// View lookup cache
private static class ViewHolder {
TextView subcategoria;
TextView descricao;
TextView descrabrev;
ImageButton favorito;
}
public CustomAdapter(ArrayList<Employee> data, Context context) {
super(context, R.layout.lista, data);
this.dataSet = data;
this.mContext=context;
}
@Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(position);
Employee dataModel=(Employee) object;
}
private int lastPosition = -1;
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
animText = AnimationUtils.loadAnimation(mContext, R.anim.anima_text);
final Employee dataModel = getItem(position);
final ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.lista, parent, false);
viewHolder.subcategoria = (TextView) convertView.findViewById(R.id.tv_subcategoria);
viewHolder.descrabrev = (TextView) convertView.findViewById(R.id.tv_descriabreviada);
viewHolder.descricao = (TextView) convertView.findViewById(R.id.tv_descricao);
viewHolder.favorito = (ImageButton)convertView.findViewById(R.id.btnFav);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
viewHolder.subcategoria.setText(dataModel.getSubcategoria());
viewHolder.descrabrev.setText(dataModel.getDescrabrev());
viewHolder.descricao.setText(dataModel.getDescricao());
if (dataModel.getFavorito().equals("1")){
viewHolder.favorito.setBackgroundResource(R.drawable.ic_fav_seleted);
}else if (dataModel.getFavorito().equals("0")){
viewHolder.favorito.setBackgroundResource(R.drawable.ic_fav);
}
viewHolder.favorito.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sub = dataModel.getSubcategoria();
if (dataModel.getFavorito().equals("1")){
fav = "0";
}else if (dataModel.getFavorito().equals("0")){
fav = "1";
}
viewHolder.favorito.startAnimation(animText);
}
});
return convertView;
}
}
How could I solve this?
Obs. The update routine was just below the DatabaseHelper getVersionId () function, I pulled it out because it was not working. The call to the update function was in the viewHolder.favorite.setOnClickListener of the above code.
NX thanks for the reply!
I made changes to the Custom Adapter by entering the codes. It looks like this:
...
//Ação ao clicar no ImageButtom
viewHolder.favorito.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sub = dataModel.getSubcategoria();
if (mOnFavoriteEmployeeListener != null) {
boolean fav = dataModel.getFavorito().equals("1");
mOnFavoriteEmployeeListener.onFavorite(dataModel, fav);
}
viewHolder.favorito.startAnimation(animText);
}
});
return convertView;
}
//Interface criada para a ação de update do favorito
interface OnFavoriteEmployeeListener {
void onFavorite(Employee e, boolean fav);
}
private OnFavoriteEmployeeListener mOnFavoriteEmployeeListener;
public void setOnFavoriteEmployeeListener(OnFavoriteEmployeeListener l) {
mOnFavoriteEmployeeListener = l;
}
But in Activity I could not see where I put the code, because I tried to put it but this is killing the application.
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ListView lv;
Animation animText;
ImageView search;
EditText textsearch;
TextView vazio;
String codigo;
//Custom Adapter
ArrayList<Employee> dataModels;
ListView listView;
private static CustomAdapter adapter;
//Final Custom Adapter
DatabaseHelper dbHelper= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
animText = AnimationUtils.loadAnimation(this, R.anim.anima_text);
search = (ImageView)findViewById(R.id.img_Search);
favoritar = (ImageButton)findViewById(R.id.btnFav);
textsearch = (EditText)findViewById(R.id.edt_Search);
vazio = (TextView)findViewById(R.id.textViewV);
vazio.setVisibility(View.INVISIBLE);
lv = (ListView) findViewById(R.id.listview);
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
codigo = textsearch.getText().toString();
search.startAnimation(animText);
if((verificaCampos(textsearch.getText().toString()) != false)) {
dbHelper = new DatabaseHelper(MainActivity.this, getFilesDir().getAbsolutePath());
try {
dbHelper.prepareDatabase();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
//Datamodels
List<Employee> list = dbHelper.getEmployees(codigo);
dataModels = new ArrayList<>();
for (int i =0; i< list.size(); i++) {
dataModels.add(list.get(i));
}
adapter = new CustomAdapter(dataModels, getApplicationContext());
lv.setAdapter(adapter);
if(adapter.isEmpty()){
vazio.setVisibility(View.VISIBLE);
}else{
vazio.setVisibility(View.INVISIBLE);
}
//Fim Data Models
}else{
mensagem();
}
}
});
//Final Pesquisa
}
private boolean verificaCampos(String campo1){
return campo1.trim().length() != 0;
}
}
ERROR
E/AndroidRuntime: FATAL EXCEPTION: main Process: br.com.projeto, PID: 25365 Theme: themes:{default=overlay:system, iconPack:system, fontPkg:system, com.android.systemui=overlay:system, com.android.systemui.navbar=overlay:system} java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.projeto/br.com.projeto.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void br.com.projeto.CustomAdapter.setOnFavoriteEmployeeListener(br.com.projeto.Cus tomAdapter$OnFavoriteEmployeeListener)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2450) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2510) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1363) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5461) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:72 6) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void br.com.projeto.CustomAdapter.setOnFavoriteEmployeeListener(br.com.projeto.Cus tomAdapter$OnFavoriteEmployeeListener)' on a null object reference at br.com.projeto.MainActivity.onCreate(MainActivity.java:118) at android.app.Activity.performCreate(Activity.java:6251) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2403) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2510) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1363) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5461) 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)
Where am I going wrong?
After the new changes
After the code changes, the logic looks like this:
CustomAdapter
....
//Ação ao clicar no ImageButtom
viewHolder.favorito.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sub = dataModel.getSubcategoria();
if (mOnFavoriteEmployeeListener != null) {
boolean fav = dataModel.getFavorito().equals("1");
mOnFavoriteEmployeeListener.onFavorite(dataModel, fav);
}
viewHolder.favorito.startAnimation(animText);
}
});
return convertView;
}
private OnFavoriteEmployeeListener mOnFavoriteEmployeeListener;
//Interface criada para a ação de update do favorito
interface OnFavoriteEmployeeListener {
void onFavorite(Employee e, boolean fav);
}
public void setOnFavoriteEmployeeListener(OnFavoriteEmployeeListener l) {
mOnFavoriteEmployeeListener = l;
}
MainActivity
...
adapter = new CustomAdapter(dataModels, getApplicationContext());
adapter.setOnFavoriteEmployeeListener(new CustomAdapter.OnFavoriteEmployeeListener() {
public void onFavorite(Employee e, boolean fav) {
dbHelper.update(e.getSubcategoria(), fav ? "1" : "0");
}
});
lv.setAdapter(adapter);
DatabaseHelper
//Faz o update da tabela ao clicar no ImageButtom
public void update(String sub, String fav){
SQLiteDatabase db = SQLiteDatabase.openDatabase(pathToSaveDBFile, null, SQLiteDatabase.OPEN_READWRITE);
String query = "UPDATE tab_mytabe SET fav = '"+fav+"' WHERE sub_categ = '"+sub+"'";
db.execSQL(query);
db.close();
}
However, it is not performing any actions on the database and does not show any apparent errors.
Resolved bank update issue
I found out what was happening, the code part of Activity was like this:
...
dbHelper.update(e.getSubcategoria(), fav ? "1" : "0");
...
When ImageButtom was clicked the update would normally happen only if the value did not change because if the value of the field in the table was "0" when clicking ImageButtom the value would still be "0", because the value true is 1, for this did not see any change. It was just changing the numbers that worked perfectly. Then with the change it was as follows:
...
dbHelper.update(e.getSubcategoria(), fav ? "0" : "1");
...