Issue
App i am trying to build crashes whenever items in listview overflows. It works fine when items are limited(<19). Please help. Any coding tips are also welcome as i am a newbie.
This is console output:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
Process: com.kmb.budget, PID: 5394
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:354)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:9446)
at android.view.ViewRootImpl.focusableViewAvailable(ViewRootImpl.java:4549)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:928)
at android.view.View.setFlags(View.java:15709)
at android.view.View.setFocusableInTouchMode(View.java:10901)
at android.widget.AdapterView.checkFocus(AdapterView.java:1168)
at android.widget.ListView.setAdapter(ListView.java:615)
>>>> at com.kmb.budget.TransactionsActivity.createTransactionList(TransactionsActivity.java:35)
>>>> at com.kmb.budget.DBClass.doInBackground(DBClass.java:116)
>>>> at com.kmb.budget.DBClass.doInBackground(DBClass.java:14)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
part of DBClass resposible to handle function. Scroll down. I had marked main lines with ">>>".
class DBClass extends AsyncTask<Void,Void,Integer> {
private MainDatabase db ;
private MainActivity mActivity;
private TransactionsActivity tActivity;
private CategoryDAO categoryDAO;
private TransactionDAO transactionDAO;
private String nm;
private String tp;
private String operation;
private String to;
private String from;
private String comment;
private int amount;
private Date createDate;
private Date transactionDate;
public DBClass(Context context,TransactionsActivity activity,String operation){
this.db = MainDatabase.getMainDatabase(context);
this.categoryDAO = db.categoryDAO();
this.transactionDAO = db.transactionDAO();
this.tActivity = activity;
this.operation = operation;
}
public DBClass(Context context,MainActivity activity,String operation){
this.db = MainDatabase.getMainDatabase(context);
this.categoryDAO = db.categoryDAO();
this.mActivity = activity;
this.operation = operation;
}
public DBClass(Context context, String nm, String tp){
this.db = MainDatabase.getMainDatabase(context);
this.categoryDAO = db.categoryDAO();
this.nm = nm;
this.tp = tp;
this.operation = "CATEGORY";
}
public DBClass(Context context, String to, String from, String comment, int amount, Date createDate, Date transactionDate) {
this.db = MainDatabase.getMainDatabase(context);
this.transactionDAO = db.transactionDAO();
this.categoryDAO = db.categoryDAO();
this.to = to;
this.from = from;
this.operation = "TRANSACTION";
this.comment = comment;
this.amount = amount;
this.createDate = createDate;
this.transactionDate = transactionDate;
}
@Override
protected Integer doInBackground(Void... voids) {
int st = 0;
switch(operation){
case("CATEGORY"):
CategoryModal category = new CategoryModal();
category.setCategoryName(nm);
category.setType(tp);
categoryDAO.insertCategory(category);
Log.i("Category created",nm);
long a = categoryDAO.getCategoryId(nm);
Log.i("Ccategory id in db",Long.toString(a));
List<String> categ= categoryDAO.getAllCategoryNames();
for(String cm : categ){
Log.i("category name" , cm);
}
break;
case("TRANSACTION"):
TransactionModal transaction = new TransactionModal();
transaction.setToId(categoryDAO.getCategoryId(to));
transaction.setFromId(categoryDAO.getCategoryId(from));
transaction.setComment(comment);
transaction.setAmount(amount);
transaction.setTransactionDate(transactionDate);
transaction.setCreateDate(createDate);
transactionDAO.insert(transaction);
Log.e("transaction",transaction.getComment());
break;
case("GET_CATEGORIES"):
try {
mActivity.setList(categoryDAO.getAllCategoryNames());
}catch (Exception e){
e.printStackTrace();
mActivity.setList(null);
}
Log.i("category call","done");
break;
case("GET_TRANSACTIONS"):
>>> List<TransactionModal> tmlist = transactionDAO.getAllTransactions();
>>> List<Transaction> list = new ArrayList<>();
>>> int i = 1;
>>> List<CategoryModal> cm = categoryDAO.getAllCategories();
>>> for(TransactionModal tm : tmlist){
>>> Long fromId = tm.getFromId();
>>> Long toId = tm.getToId();
>>> Transaction t = new Transaction(Integer.toString(i),categoryDAO.getCategoryName(fromId),categoryDAO.getCategoryName(toId),tm.getComment(),tm.getTransactionDate().toString(),Integer.toString(tm.getAmount()));
>>> CategoryModal cmc = categoryDAO.getCategoryById(tm.getFromId());
>>> String to = cmc.getCategoryName();
>>> list.add(t);
>>> i++;
>>> }
>>> tActivity.createTransactionList(list);
break;
case("convertOperation"):
break;
}
return st;
}
}
this is transaction activity
27 public void createTransactionList(List<Transaction> list){
28 Transaction header = new Transaction("SR","From","To","Comment","Date","Amount");
29 List<Transaction> temp = new ArrayList<>();
30 temp.add(header);
31 temp.addAll(list);
32 ListView transactionListView = findViewById(R.id.transactions_listView);
33 List<Transaction> transactionsList = temp;
34 TransactionListAdapter tLAdapter = new TransactionListAdapter(this,R.layout.transaction_list_adapter,transactionsList);
35 transactionListView.setAdapter(tLAdapter);
36 }
this is conent_transaction.xml which contains listView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".TransactionsActivity"
tools:showIn="@layout/activity_transactions">
<ListView
android:id="@+id/transactions_listView"
android:layout_width="match_parent"
android:scrollbars="vertical"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
Edit 1: Transaction list adapter
class TransactionListAdapter extends ArrayAdapter<Transaction> {
private Context context;
private int resource;
/**
* Default constructor for transaction adapter
* @param context
* @param resource
* @param objects
*/
public TransactionListAdapter(@NonNull Context context, int resource, @NonNull List<Transaction> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
String sr = getItem(position).getSr();
String from = getItem(position).getFrom();
String to = getItem(position).getTo();
String comment = getItem(position).getComment();
String date = getItem(position).getDate();
String amount = getItem(position).getAmount();
Transaction transaction = getItem(position);
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(resource,parent,false);
TextView tvSr = convertView.findViewById(R.id.tr_list_sr);
TextView tvTo = convertView.findViewById(R.id.tr_list_to);
TextView tvFrom = convertView.findViewById(R.id.tr_list_from);
TextView tvComment = convertView.findViewById(R.id.tr_list_comment);
TextView tvDate = convertView.findViewById(R.id.tr_list_td);
TextView tvAmount = convertView.findViewById(R.id.tr_list_amount);
tvSr.setText(sr);
tvTo.setText(to);
tvFrom.setText(from);
tvComment.setText(comment);
tvAmount.setText(amount);
tvDate.setText(date);
return convertView;
}
}
overflows: increase beyond a certain number which can be viewed on screen
Solution
You try to update View
from inside AsyncTask's doInBackground()
, which is not permissible. Update your DBClass
like below:
class DBClass extends AsyncTask<Void,Void,List<?>> {
....
@Override
protected List<?> doInBackground(Void... voids) {
List mList = null;
switch(operation) {
....
case("GET_CATEGORIES"):
try {
mList = categoryDAO.getAllCategoryNames();
}catch (Exception e){
e.printStackTrace();
}
break;
case("GET_TRANSACTIONS"):
....
mList = list;
break;
}
return mList;
}
@Override
protected void onPostExecute(List<?> list) {
switch(operation) {
case("GET_CATEGORIES"):
mActivity.setList(list);
break;
case("GET_TRANSACTIONS"):
tActivity.createTransactionList(list);
break;
}
}
}
Answered By - Md. Asaduzzaman
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.