I'm trying to build a "Note taking" area in my app. I'm having problems with the view binding specifically. i followed this code example "https://codingwithsaud.medium.com/how-to-make-note-app-in-android-studio-part-1-443ccf16921e" to a T, but its mainly built in an activity not a fragment. I'm currently building it in an fragment and everything else is good besides my "Equipment_Tracker.kt" i cant figure out whats going wrong. The list problems take place in the "Equipment_Tracker.kt" Thanks in advance for helping.
List off errors popping up.
Unresolved reference: setContentView
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Type mismatch: inferred type is Equipment_Tracker but Context? was expected
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
None of the following functions can be called with the arguments supplied:
public constructor Intent(p0: Context!, p1: Class<*>!) defined in android.content.Intent
public constructor Intent(p0: String!, p1: Uri!) defined in android.content.Intent
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
Smart cast to 'FragmentEquipmentTrackerBinding' is impossible, because 'binding' is a mutable property that could have been changed by this time
None of the following functions can be called with the arguments supplied:
public open fun makeText(p0: Context!, p1: CharSequence!, p2: Int): Toast! defined in android.widget.Toast
public open fun makeText(p0: Context!, p1: Int, p2: Int): Toast! defined in android.widget.Toast
None of the following functions can be called with the arguments supplied:
public open fun makeText(p0: Context!, p1: CharSequence!, p2: Int): Toast! defined in android.widget.Toast
public open fun makeText(p0: Context!, p1: Int, p2: Int): Toast! defined in android.widget.Toast
Equipment_Tracker.kt
package com.example.armymaintenance
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.example.armymaintenance.Model.note_model
import com.example.armymaintenance.database.MySqliteHelper
import com.example.armymaintenance.databinding.FragmentEquipmentTrackerBinding
class Equipment_Tracker : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_equipment__tracker, container, false)
}
var binding: FragmentEquipmentTrackerBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = FragmentEquipmentTrackerBinding.inflate(layoutInflater)
setContentView(binding.getRoot())
val helper = MySqliteHelper(this)
binding.btnDisplay.setOnClickListener(View.OnClickListener {
val intent = Intent(this#Equipment_Tracker, Equipment_Tracker::class.java)
startActivity(intent)
})
binding.btnSave.setOnClickListener(View.OnClickListener {
val model = note_model()
model.bumpernumber = binding.bumpernumber.text.toString()
model.description = binding.description.text.toString()
model.nsn = binding.nsn.text.toString()
model.serialnumber = binding.serialnumber.text.toString()
model.date = binding.date.text.toString()
if (model.bumpernumber.isEmpty()) {
binding.bumpernumber.error = "Enter bumper number"
return#OnClickListener
}
if (model.description.isEmpty()) {
binding.description.error = "Enter description"
return#OnClickListener
}
if (model.nsn.isEmpty()) {
binding.nsn.error = "Enter nsn"
return#OnClickListener
}
if (model.serialnumber.isEmpty()) {
binding.serialnumber.error = "Enter serial number"
return#OnClickListener
}
if (model.date.isEmpty()) {
binding.date.error = "Enter date"
return#OnClickListener
}
val r = helper.saveNote(model)
if (r) {
Toast.makeText(this#Equipment_Tracker, "note is saved", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this#Equipment_Tracker, "some thing want wrong", Toast.LENGTH_SHORT)
.show()
}
})
}
}
fragment_equipment_tracker.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Equipment_Tracker">
<LinearLayout
android:layout_centerInParent="true"
android:padding="10dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/bumpernumber"
android:hint="Bumper Number"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/description"
android:hint="Enter description"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/nsn"
android:hint="Enter nsn"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/serialnumber"
android:hint="Enter serial number"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/date"
android:hint="Enter date"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/btnSave"
android:text="Save"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/btnDisplay"
android:text="Display"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
note_model.java
package com.example.armymaintenance.Model;
public class note_model {
private int id;
private String bumpernumber;
private String description;
private String nsn;
private String serialnumber;
private String date;
public note_model() {
}
public note_model(int id, String bumpernumber, String description, String nsn, String serialnumber, String date) {
this.id = id;
this.bumpernumber = bumpernumber;
this.description = description;
this.nsn = nsn;
this.serialnumber = serialnumber;
this.date = date;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBumpernumber() {
return bumpernumber;
}
public void setBumpernumber(String bumpernumber) {
this.bumpernumber = bumpernumber;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getNsn() {
return nsn;
}
public void setNsn(String nsn) {
this.nsn = nsn;
}
public String getSerialnumber() {
return serialnumber;
}
public void setSerialnumber(String serialnumber) {
this.serialnumber = serialnumber;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
MySqliteHelper.java
package com.example.armymaintenance.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
import com.example.armymaintenance.Model.note_model;
import java.util.ArrayList;
import java.util.List;
public class MySqliteHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME="note.db";
private static final int VERSION=1;
public MySqliteHelper(#Nullable Context context) {
super(context, DATABASE_NAME, null, VERSION);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String table1="create table "+TableSchema.note.TABLE_NAME+"("+TableSchema.note.ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+TableSchema.note.BUMPERNUMBER+" TEXT, "+TableSchema.note.DESCRIPTION+" TEXT,"+TableSchema.note.NSN+" TEXT,"+TableSchema.note.SERIALNUMBER+" TEXT, "+TableSchema.note.DATE+" TEXT );";
sqLiteDatabase.execSQL(table1);
}
public boolean saveNote(note_model model){
SQLiteDatabase database=this.getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(TableSchema.note.BUMPERNUMBER,model.getBumpernumber());
cv.put(TableSchema.note.DESCRIPTION,model.getDescription());
cv.put(TableSchema.note.NSN,model.getNsn());
cv.put(TableSchema.note.SERIALNUMBER,model.getSerialnumber());
cv.put(TableSchema.note.DATE,model.getDate());
long id= database.insert(TableSchema.note.TABLE_NAME,null,cv);
if (id==-1){
return false;
}
return true;
}
public List<note_model> getAllNotes(){
SQLiteDatabase database= this.getReadableDatabase();
String[] cols={TableSchema.note.ID,TableSchema.note.BUMPERNUMBER,TableSchema.note.DESCRIPTION,TableSchema.note.NSN,TableSchema.note.SERIALNUMBER,TableSchema.note.DATE};
Cursor cursor=database.query(TableSchema.note.TABLE_NAME,cols,null,null,null,null,TableSchema.note.ID+" DESC");
ArrayList<note_model> list=new ArrayList<>();
while (cursor.moveToNext()){
note_model model=new note_model();
model.setId(cursor.getInt(cursor.getColumnIndex(TableSchema.note.ID)));
model.setBumpernumber(cursor.getString(cursor.getColumnIndex(TableSchema.note.BUMPERNUMBER)));
model.setDescription(cursor.getString(cursor.getColumnIndex(TableSchema.note.DESCRIPTION)));
model.setNsn(cursor.getString(cursor.getColumnIndex(TableSchema.note.NSN)));
model.setSerialnumber(cursor.getString(cursor.getColumnIndex(TableSchema.note.SERIALNUMBER)));
model.setDate(cursor.getString(cursor.getColumnIndex(TableSchema.note.DATE)));
list.add(model);
}
cursor.close();
database.close();
return list;
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
if (i<i1){
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS "+TableSchema.note.TABLE_NAME);
}
}
}
TableSchema.java
package com.example.armymaintenance.database;
public class TableSchema {
public static class note{
public static final String TABLE_NAME="tbl_note";
public static final String ID="id";
public static final String BUMPERNUMBER="bumpernumber";
public static final String DESCRIPTION="description";
public static final String NSN="nsn";
public static final String SERIALNUMBER="serialnumber";
public static final String DATE="date";
}
}
Binding is wrong Please check this documentation for the view Binding
https://developer.android.com/topic/libraries/view-binding#kts
In Activity you can initialize the lateinit var binding: ActivityMainBinding
and can inflate the view like this
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
But for the fragments the way is different
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
and in onCreateView method you have to do it like this
_binding = FragmentMainBinding.inflate(inflater, container, false)
val view = binding.root
return view
Please make sure that you do it in onCreateView not in onViewCreated
and in onDestroyView you have to set its value to null
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
That is the Proper way of doing binding you can also visit the documentation for more information
Related
I followed this guide How to display data from Firestore in a RecyclerView with Android?, but am facing a NullPointerException in the setter in the ViewHolder. I'm also actually very unsure of what to do in the setter in the ViewHolder...
![database]https://imgur.com/a/wquZ08f
Model:
public class FoodModel {
private String foodName;
private String foodType;
private String foodQty;
private String foodExpDate;
public FoodModel() {}
public FoodModel(String name, String type, String qty, String expDate) {
this.foodName = name;
this.foodType = type;
this.foodQty = qty;
this.foodExpDate = expDate;
}
public String getFoodName() {return foodName;}
public void setFoodName(String name) {foodName = name;}
public String getFoodType() {return foodType;}
public void setFoodType(String type) {foodType = type;}
public String getFoodQty() {return foodQty;}
public void setFoodQty(String qty) {foodQty = qty;}
public String getFoodExpDate() {return foodExpDate;}
public void setFoodExpDate(String expDate) {foodExpDate = expDate;}
}
Activity code:
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
Query foodQuery = db.collection("Food")
.orderBy("food_name", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<FoodModel> options = new FirestoreRecyclerOptions.Builder<FoodModel>()
.setQuery(foodQuery, FoodModel.class)
.build();
adapter = new FirestoreRecyclerAdapter<FoodModel, FoodViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull FoodViewHolder holder, int position, #NonNull FoodModel model) {
holder.setFoodName(model.getFoodName());
}
#NonNull
#Override
public FoodViewHolder onCreateViewHolder(#NonNull ViewGroup group, int viewType) {
View view = LayoutInflater.from(group.getContext()).inflate(R.layout.recycler_view_row, group, false);
return new FoodViewHolder(view);
}
};
recyclerView.setAdapter(adapter);
}
private class FoodViewHolder extends RecyclerView.ViewHolder {
private View view;
FoodViewHolder(View itemView) {
super(itemView);
view = itemView;
}
void setFoodName(String foodName) {
TextView textView = view.findViewById(R.id.editName);
textView.setText(foodName);
}
}
xml of recycler_view_row:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/foodListRow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
errors:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.qremind, PID: 17735
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.qremind.FoodList$FoodViewHolder.setFoodName(FoodList.java:91)
at com.example.qremind.FoodList$1.onBindViewHolder(FoodList.java:70)
at com.example.qremind.FoodList$1.onBindViewHolder(FoodList.java:67)
at com.firebase.ui.firestore.FirestoreRecyclerAdapter.onBindViewHolder(FirestoreRecyclerAdapter.java:158)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1897)
at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:414)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:878)
at android.view.Choreographer.doCallbacks(Choreographer.java:690)
at android.view.Choreographer.doFrame(Choreographer.java:622)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:864)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:185)
at android.app.ActivityThread.main(ActivityThread.java:6473)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:916)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:806)
You have defined the Textview inside the function. Define it as
private class FoodViewHolder extends RecyclerView.ViewHolder {
private View view;
TextView textView;
FoodViewHolder(View itemView) {
super(itemView);
view = itemView;
textView = view.findViewById(R.id.editName);
}
void setFoodName(String foodName) {
textView.setText(foodName);
}
}
Change this:
TextView textView = view.findViewById(R.id.editName);
into this:
TextView textView = view.findViewById(R.id.foodListRow);
In FoodViewHolder class:
This method:
void setFoodName(String foodName) {
//here is your problem
TextView textView = view.findViewById(R.id.editName);
textView.setText(foodName);
}
Must be like this, you are pointing to the wrong ID:
void setFoodName(String foodName) {
TextView textView = view.findViewById(R.id.foodListRow);
textView.setText(foodName);
}
I have got an error about no such talbe: Account while I am calling data from database.
My database name is "account.db" and table name is "Account". There are two columns, first is "name" and second is "email".
I am writing in kotlin language. Please look at below for my DBHelper and DBManager.
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.os.Build
import android.widget.Toast
import java.io.FileOutputStream
import java.io.IOException
import java.lang.Exception
import java.util.ArrayList
class DbManager {
var DB_PATH = ""
var DB_NAME = "account.db"
val dbVersion = 1
//CREATE TABLE IF NOT EXISTS MyNotes (ID INTEGER PRIMARY KEY,title TEXT, Description TEXT);"
// val sqlCreateTable = "CREATE TABLE IF NOT EXISTS " + dbTable + " (" + colID + " INTEGER PRIMARY KEY," +
// colTitle + " TEXT, " + colDes + " TEXT);"
var sqlDB: SQLiteDatabase? = null
constructor(context: Context) {
var db = DBHelper(context)
sqlDB = db.writableDatabase
}
inner class DBHelper(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, dbVersion) {
var mDatabase: SQLiteDatabase? = null
var mContext: Context? = null
//Todo: Get All Data users
fun getAllUsers(): List<Account>?{
val temp = ArrayList<Account>()
val db = writableDatabase
var c: Cursor?
try {
c = db.rawQuery("SELECT * FROM Account ", null)
if (c == null) return null
c.moveToFirst()
do {
val account = Account(c.getString(c.getColumnIndex("name")), c.getString(c.getColumnIndex("email")))
temp.add(account)
} while (c.moveToNext())
c.close()
} catch (e: Exception) {
}
db.close()
return temp
}
fun createDataBase() {
//Todo: Create Database
val isDBExist = checkDataBase()
if (isDBExist) { } else {
this.readableDatabase
try {
copyDataBase()
Toast.makeText(this.mContext, "Copy has been finished.", Toast.LENGTH_SHORT).show()
} catch (ex: Exception) {
}
}
}
init {
if (Build.VERSION.SDK_INT > 17) {
DB_PATH = context.applicationInfo.dataDir + "/databases/"
} else {
DB_PATH = "/data/data/" + context.packageName + "/databases/"
}
this.mContext = mContext
}
override fun close() {
if (mDatabase != null)
mDatabase!!.close()
super.close()
}
fun checkDataBase(): Boolean {
//Todo: Check Database
var tempDB: SQLiteDatabase? = null
try {
val path = DB_PATH + DB_NAME
tempDB = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY)
} catch (ex: Exception) {
}
if (tempDB != null)
tempDB.close()
return if (tempDB != null) true else false
}
fun copyDataBase() {
//Todo:Copy Database
try {
val myInput = mContext!!.assets.open(DB_NAME)
val outputFileName = DB_PATH + DB_NAME
val myOutput = FileOutputStream(outputFileName)
val buffer = ByteArray(1024)
var length: Int
length= myInput.read(buffer)
while (length > 0) {
myOutput.write(buffer, 0, length)
}
myOutput.flush()
myOutput.close()
myInput.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
fun openDataBase() {
//Todo: Open Database
val path = DB_PATH + DB_NAME
mDatabase = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE)
}
override fun onCreate(db: SQLiteDatabase) {
createDataBase()
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
if(oldVersion>=newVersion){
copyDataBase()
}
}
// companion object {
// var DB_PATH = ""
// var DB_NAME = "account.db"
// }
}
}
Here is my MainActivity.kt
import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.row.*
import kotlinx.android.synthetic.main.row.view.*
import java.util.ArrayList
class MainActivity : AppCompatActivity() {
var lstUsers=ArrayList<Account>()
lateinit var dbHelper: DBHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
dbHelper = DBHelper(applicationContext)
dbHelper.createDataBase()
}
fun buGetData(v: View){
//Todo: Load Data from db set to listview
LoadData()
}
fun LoadData(){
val accout = dbHelper.getAllUsers()
//this.listView.removeAllViews()
//List View
for (list in accout!!) {
lstUsers.add(list)
}
var myNotesAdapter= MyAdapter(this, lstUsers)
listView.adapter=myNotesAdapter
}
inner class MyAdapter:BaseAdapter {
var listMyAdapter = ArrayList<Account>()
var context:Context?=null
constructor(context:Context, listMyAdapter:ArrayList<Account>):super(){
this.listMyAdapter=listMyAdapter
this.context=context
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var myView=layoutInflater.inflate(R.layout.row,null)
var myAc=listMyAdapter[position]
myView.txtUser.text = myAc.userName
myView.txtEmail.text = myAc.email
return myView
}
override fun getItem(position: Int): Any {
return listMyAdapter[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return listMyAdapter.size
}
}
}
The error has shown like the picture below.
Please help me to solve it. Best regards, Sai Tawng Pha
I have solved my problem with update a few line of code. I want to share for other people.
If some one want to read exist Database file from Assests folder with Kotlin. Please have look below.
MainActivity.kt
import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.row.*
import kotlinx.android.synthetic.main.row.view.*
import java.util.ArrayList
class MainActivity : AppCompatActivity() {
var lstUsers=ArrayList<Account>()
var dbHelper: DBHelper? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
dbHelper = DBHelper(this)
dbHelper!!.createDatabase()
}
fun buGetData(v: View){
lstUsers = this.dbHelper!!.getAllUsers() as ArrayList<Account>
this.container.removeAllViews()
//List View
for (account in lstUsers) {
// val inflater = baseContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
// val addView = inflater.inflate(R.layout.row, null)
var addView = layoutInflater.inflate(R.layout.row,null)
addView.txtUser.text = account.userName
addView.txtEmail.text = account.email
//add View
container.addView(addView)
}
}
}
DBHelper.kt
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.util.Log;
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 DbHelper extends SQLiteOpenHelper {
private static String DB_PATH= "";
private static String DB_NAME= "account.db";
private SQLiteDatabase mDatabase;
private final Context mContext;
public DbHelper(Context context) {
super(context, DB_NAME, null, 11);
this.mContext = context;
if(Build.VERSION.SDK_INT >= 17){
this.DB_PATH = context.getApplicationInfo().dataDir+"/databases/";
Log.e("Path:", DB_PATH);
}else {
this.DB_PATH = "/data/data/"+context.getPackageName()+"/databases/";
Log.e("Path:", DB_PATH);
}
}
#Override
public synchronized void close() {
if(mDatabase != null){
mDatabase.close();
}
super.close();
}
private boolean checkDatabase(){
//Todo: Check Database
SQLiteDatabase tempDB = null;
try {
String path = DB_PATH+DB_NAME;
tempDB = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
}catch (Exception ex){}
if(tempDB!=null){
tempDB.close();
}
return tempDB!=null?true:false;
}
public void copyDatabase(){
//Todo: Copy Database
try {
InputStream myInput = mContext.getAssets().open(DB_NAME);
String outputFileName = DB_PATH+DB_NAME;
OutputStream myOutput = new FileOutputStream(outputFileName);
byte[] buffer = new byte[1024];
int length;
while ((length=myInput.read(buffer))>0){
myOutput.write(buffer,0,length);
}
myOutput.flush();
myOutput.close();
myInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void openDatabase(){
//Todo: Open Database
String path = DB_PATH+DB_NAME;
mDatabase = SQLiteDatabase.openDatabase(path,null, SQLiteDatabase.OPEN_READWRITE);
}
public void createDatabase(){
//Todo: Create Database
boolean isDBExist = checkDatabase();
if (isDBExist){
}else {
this.getReadableDatabase();
try {
copyDatabase();
}catch (Exception e){throw new Error("Copy Database Error");}
}
}
public List<Account>getAllUsers(){
//Todo: Get All Users
List<Account> temp = new ArrayList<Account>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor c;
try {
c = db.rawQuery("SELECT * FROM Account", null);
if (c==null) return null;
c.moveToFirst();
do {
Account account = new Account(c.getString(c.getColumnIndex("name")),(c.getString(c.getColumnIndex("email"))));
temp.add(account);
}while (c.moveToNext());
c.close();
}catch (Exception e){}
db.close();
return temp;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/buGetData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Get Data" />
<LinearLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/buGetData"
android:layout_centerHorizontal="true"
android:layout_marginTop="-15dp"
android:orientation="vertical"></LinearLayout>
</RelativeLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/txtUserName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="TextView"
android:textSize="18sp" />
<TextView
android:id="#+id/txtEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="TextView" />
</LinearLayout>
Please look the screenshot below.
Note: Please replace your Database file from Assets folder and change the name of your database name and table name from DBHelper.kt at createDataBase Function.
I hope, it will be useful for you.
I really don't know where I am going wrong. According to the documentation I am doing everything right. I am doubtful if it's happening just because I am using TabbedActivity and dealing with fragments, but still I don't know how it's wrong.
Please look into the code and help me out. I have been struggling a lot to achieve this task of retrieving and displaying data from FIREBASE.
And being a beginner in this, it's quite hard for me to figure it out.
MainActivity.Java
package com.example.souravkumar.sqaurewallpapers;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
public class MainActivity extends AppCompatActivity {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
int count=0;
public FloatingActionButton mAddImage;
private StorageReference mStorage;
public DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
String stringUri;
Long date;
private static final int GALLERY_INTENT = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mStorage = FirebaseStorage.getInstance().getReference();
mAddImage = (FloatingActionButton) findViewById(R.id.addImage);
mAddImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, GALLERY_INTENT);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GALLERY_INTENT && resultCode == RESULT_OK) {
Uri uri = data.getData();
StorageReference filePath = mStorage.child("Wallpapers").child(uri.getLastPathSegment());
filePath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, "Upload Successful", Toast.LENGTH_LONG).show();
Uri downloadUrl = taskSnapshot.getDownloadUrl();
//Adding image to the database
stringUri= downloadUrl.toString();
date = System.currentTimeMillis();
addImageToDatabase (stringUri, date);
}
});
}
}
private void addImageToDatabase(String downloadUrl, Long date){
image_details id= new image_details(downloadUrl, date);
String key = mDatabase.push().getKey();
mDatabase.child(key).child("URL").setValue(id.getUrl());
mDatabase.child(key).child("Date").setValue(id.getDate());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
GridView gridView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (getArguments().getInt(ARG_SECTION_NUMBER) == 1) {
View rootView = inflater.inflate(R.layout.fragment_popular, container, false);
return rootView;
} else if (getArguments().getInt(ARG_SECTION_NUMBER) == 2) {
View rootView = inflater.inflate(R.layout.fragment_recent, container, false);
return rootView;
} else
return inflater.inflate(R.layout.fragment_main, container, false);
}
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "POPULAR";
case 1:
return "RECENT";
case 2:
return "PROFILES";
}
return null;
}
}
}
Popular.Java
package com.example.souravkumar.sqaurewallpapers;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.squareup.picasso.Picasso;
/**
* Created by Sourav Kumar on 11/3/2017.
*/
public class popular extends FragmentActivity {
private RecyclerView recyclerView;
private DatabaseReference myRef;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
myRef = FirebaseDatabase.getInstance().getReference();
FirebaseRecyclerAdapter<image_details,BlogViewHolder> recyclerAdapter=new FirebaseRecyclerAdapter<image_details,BlogViewHolder>(
image_details.class,
R.layout.individual_row,
BlogViewHolder.class,
myRef
) {
#Override
protected void populateViewHolder(BlogViewHolder viewHolder, image_details model, int position) {
viewHolder.setUrl(model.getUrl());
viewHolder.setDate(model.getDate());
}
};
recyclerView.setAdapter(recyclerAdapter);
}
public static class BlogViewHolder extends RecyclerView.ViewHolder {
View mView;
TextView textView;
ImageView imageView;
public BlogViewHolder(View itemView) {
super(itemView);
mView=itemView;
textView = (TextView)itemView.findViewById(R.id.date);
imageView = (ImageView)itemView.findViewById(R.id.imageView);
}
public void setDate(Long date) {
textView.setText(date.toString());
}
public void setUrl(String url) {
Picasso.with(mView.getContext())
.load(url)
.resize(50, 50)
.centerCrop()
.into(imageView);
}
}
}
image_details.Java
package com.example.souravkumar.sqaurewallpapers;
/**
* Created by Sourav Kumar on 10/29/2017.
*/
public class image_details {
String url;
Long date;
image_details(){}
public image_details(String url, Long date){
this.url = url;
this.date = date;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Long getDate() {
return date;
}
public void setDate(Long date) {
this.date = date;
}
}
fragment_popular.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.souravkumar.sqaurewallpapers.popular">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerView">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
individual_row.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="150dp"
android:layout_height="280dp"
android:id="#+id/imageView"
android:src="#mipmap/ic_launcher"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Date"
android:id="#+id/date"/>
</LinearLayout>
</android.support.v7.widget.CardView>
SimpleCustomAdapter worked and populated my ListView, but then I wanted to implement a delete ImageButton within the ListView. To achieve that I had to make a custom adapter. Now it doesn't show data in ListView.
This is my MainActivity.java where I put the MyListAdapter class too (at the bottom). I am a beginner so I am aware that code might be all over the place. MainAcitivty has call for adapter, a setonclicklistener for listview which also sends id of item in sharedpreferences so I can catch it in deleteNotes within adapter. Also, delete button works perfectly fine and I can delete notes, but the only problem is that Title and Date dont show in ListView, whereas before they did. Thanks
package com.example.android.notepad2;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.media.Image;
import android.preference.PreferenceManager;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import static com.example.android.notepad2.R.id.parent;
import static com.example.android.notepad2.R.layout.listtemplate;
public class MainActivity extends AppCompatActivity {
NDb mydb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mydb = new NDb(this);
ListView listview;
// listview
listview = (ListView) findViewById(R.id.listview);
String[] array = new String[] {mydb.name, mydb.date};
int[] display = new int[] {R.id.title, R.id.date};
Cursor c = mydb.fetchAll();
MyListAdapter adapter = new MyListAdapter(this, listtemplate, c, array, display, 0);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Bundle dataBundle = new Bundle();
dataBundle.putInt("id", (int)l);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("ajdi", (int)l);
editor.apply();
Intent intent = new Intent(MainActivity.this, NoteDisplay.class);
intent.putExtras(dataBundle);
MainActivity.this.startActivity(intent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.add_note:
Bundle dataBundle = new Bundle();
dataBundle.putInt("id", 0);
Intent intent = new Intent(MainActivity.this,NoteDisplay.class);
intent.putExtras(dataBundle);
MainActivity.this.startActivity(intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public class MyListAdapter extends SimpleCursorAdapter{
private LayoutInflater mInflater;
private Context context;
private int layout;
public MyListAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags){
super(context, layout, c, from, to, flags);
this.context = context;
this.layout = layout;
mInflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup par){
ViewHolder holder;
if(convertView==null){
mInflater = LayoutInflater.from(getBaseContext());
convertView = mInflater.inflate(R.layout.listtemplate, null);
holder = new ViewHolder();
holder.btn = (ImageButton) convertView.findViewById(R.id.delete_note);
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.date = (TextView) convertView.findViewById(R.id.date);
holder.btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
int l = sp.getInt("ajdi", 0);
if (l != 0) {
mydb.deleteNotes(l);
Toast.makeText(MainActivity.this, "Deleted", Toast.LENGTH_SHORT).show();
finish();
startActivity(getIntent());
}
}
});
convertView.setTag(holder);
}else{
holder= (ViewHolder) convertView.getTag();
}
return convertView;
}
}
public class ViewHolder{
ImageButton btn;
TextView title;
TextView date;
}
}
This is my Database java file.
package com.example.android.notepad2;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by DelicAnte on 04.10.2017..
*/
public class NDb extends SQLiteOpenHelper {
public static final String dbname = "mydb";
public static final String mynotes = "mynotes";
public static final String _id = "_id";
public static final String name = "name";
public static final String content = "content";
public static final String date = "date";
SQLiteDatabase db;
public NDb(Context context){
super(context,dbname,null,1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table mynotes"
+"(_id integer primary key, name text, content text, date text)");
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS" + mynotes);
onCreate(db);
}
public boolean insertNotes(String name, String content, String date){
db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("content", content);
contentValues.put("date", date);
db.insert(mynotes, null, contentValues);
return true;
}
public Cursor fetchAll(){
db = this.getReadableDatabase();
Cursor mCursor = db.query(mynotes, new String[] {"_id", "name", "content", "date"}, null, null, null, null, null);
if(mCursor!=null){
mCursor.moveToFirst();
}
return mCursor;
}
public Integer deleteNotes(Integer id){
db = this.getWritableDatabase();
return db.delete(mynotes, "_id=?", new String[] {Integer.toString(id)});
}
public Cursor getData(int id){
db = this.getReadableDatabase();
Cursor c = db.rawQuery("select * from " + mynotes +" where _id=" + id + "", null);
return c;
}
}
This is my listtemplate.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2"
>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/title"
android:textSize="22sp"
android:layout_weight="1"
android:paddingBottom="15dp"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/date"
android:textSize="14sp"
android:layout_weight="0.5"
/>
<ImageButton
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:src="#drawable/delete_note"
android:layout_weight="0.5"
android:focusable="false"
android:id="#+id/delete_note"
/>
<!-- android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"-->
</LinearLayout>
</LinearLayout>
If anyone might be interested. I solved this by adding adapter.bindView in mainactivity.java. In that method you set text for title, content and finally a button setonclicklistener.
My app uses a cursorloader to populate sqlite data into a ListView. Actually, the cursorloader should only populate one column (COLUNM_NAME_SITE) from the DB into the listview. The issue I have is once information is inserted in the db, a list item is created ( I can tell by the row lines shown every time data is inserted) but no text is shown in the listview the listview is basically blank. I believe this also makes the app crash once the list view item is clicked.
I assume my FROM and TO arrays and Cursor Adapter are created properly but I can be wrong. Could the issue be with my Layout? I’m not sure but am hoping someone will take a in depth look at my code and let me know where I went wrong.
I do not receive any errors until I click on the blank listview item.
Loader Class:
public class LoginList extends FragmentActivity implements AdapterView.OnItemClickListener, OnClickListener, LoaderManager.LoaderCallbacks<Cursor> {
private ListView loginList;
private Button webLogin;
private SimpleCursorAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)findViewById(R.id.button3);
webLogin.setOnClickListener(this);
//Specify fileds to display in the list
String[] from = new String[] { ListProvider.COLUMN_NAME_SITE };
//Bind fields to listview
int[] to = new int[] {R.id.loginlist };
// Create CursorAdapter and set it to display
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, from, to);
loginList.setAdapter(adapter);
getSupportLoaderManager().initLoader(0, null, this);
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Selected ID :" + arg2, Toast.LENGTH_SHORT).show();
Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
Cursor clickedObject = (Cursor)loginList.getItemAtPosition(arg2);
Bundle loginBundle = new Bundle();
loginBundle.putString("clickedWebSite",((LoginDetails) clickedObject).getsName());
loginBundle.putString("clickedWebAddress",((LoginDetails) clickedObject).getwUrl());
loginBundle.putString("clickedUserName",((LoginDetails) clickedObject).getuName());
loginBundle.putString("clickedPassWord",((LoginDetails) clickedObject).getpWord());
loginBundle.putString("clickedNotes",((LoginDetails) clickedObject).getlNotes());
updateDeleteLoginInfo.putExtras(loginBundle);
startActivityForResult(updateDeleteLoginInfo, 0);
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
#Override
public Loader<Cursor> onCreateLoader(int ignored, final Bundle args) {
return new CursorLoader(this, ListProvider.CONTENT_URI, null, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor);
}
#Override
public void onLoaderReset (Loader<Cursor> loader) {
adapter.swapCursor(null);
}
}
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ns="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="#+id/loginlist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/button3"
android:layout_alignParentTop="true" />
<Button
android:id="#+id/button3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:text="ADD" />
</RelativeLayout>
Database:
//Database Columns
public static final String COLUMN_ROWID = "_id";
public static final String COLUMN_NAME_SITE = "sName";
public static final String COLUMN_NAME_ADDRESS = "wUrl";
public static final String COLUMN_NAME_USERNAME = "uName";
public static final String COLUMN_NAME_PASSWORD = "pWord";
public static final String COLUMN_NAME_NOTES = "lNotes";
// Database related Constants
public static final String DATABASE_NAME = "SiteLogindb";
public static final int DATABASE_VERSION = 2;
public static final String DSTORE_CREATE = "create table if not exists " +
TABLE_NAME_INFOTABLE + " ("+ COLUMN_ROWID + " integer primary key autoincrement,"
+ COLUMN_NAME_SITE + " text not null,"
+ COLUMN_NAME_ADDRESS + " text not null,"
+ COLUMN_NAME_USERNAME + " text not null,"
+ COLUMN_NAME_PASSWORD + " text not null,"
+ COLUMN_NAME_NOTES + " text not null);";
A different way you can accomplish this is to extend ListActivity and implement LoaderManager.LoaderCallbacks.
public class LoginActivity extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor> {...
There is a good 4 part tutorial on this over at the Android Design Patterns blog.