简体   繁体   中英

RecylerView won't populate

UPDATE AFTER DEBUGGING

It turns out that convertCursorToTransactionInfoList and transactionLoadComplete are never actually running. I put break points on them and they never showed up in the debugger. Also, adapterData: size = 0 is showing when running the debugger.

I was able to properly populate ONE ITEM of the recycler view using the code in onCreateView under TransactionInfo returnListValue = new TransactionInfo();

Can anyone provide some insight into why this wouldn't be working? The more and more I do this, I'm thinking it has to do with either ArrayList<> and List<> descrepancies because ArrayList<> is used in TransactionsTab.java whereas in AdapterTransactions.java , List<> is used OR TransactionInfo.java in some aspect. I've posted all of these classes below.

The SQLite interface isn't the problem (I'm pretty sure) as I'm using it elsewhere in the app to populate Spinners using SimpleCursorAdapter .

TransactionsTab.java:

public class TransactionsTab extends Fragment
    implements TransactionLoad.LoadComplete {

RecyclerView transactionsRecycler;
AdapterTransactions adapter;
TransactionLoad load = null;
Cursor cursor;
ArrayList<TransactionInfo> adapterData = new ArrayList<>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    load = new TransactionLoad(getActivity());
    load.execute();
}

@Override
public View onCreateView(LayoutInflater inflater,
                         @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.tab_transactions,container,false);
    transactionsRecycler = (RecyclerView) view.findViewById(R.id.transactionRecycler);
    adapter = new AdapterTransactions(getActivity(), adapterData);
    transactionsRecycler.setAdapter(adapter);
    transactionsRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));

    TransactionInfo returnListValue = new TransactionInfo();
    returnListValue.itemName = "lunch";
    returnListValue.itemCat = "Food";
    returnListValue.itemCurrency = "KRW";
    returnListValue.itemPrice = "125";
    returnListValue.date = "2015/08/25; 17:25:32";
    adapterData.add(returnListValue);

    return view;
}

private void convertCursorToTransactionInfoList(Cursor cursor) {
    if (cursor != null) {
        while (cursor.moveToNext()) {
            TransactionInfo returnListValue = new TransactionInfo();
            returnListValue.itemName = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_NAME));
            returnListValue.itemCat = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CATEGORY));
            returnListValue.itemCurrency = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CURRENCY));
            returnListValue.itemPrice = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_PRICE));
            returnListValue.date = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_DATE));
            adapterData.add(returnListValue);
        }
    }
}

@Override
public void transactionLoadComplete(Cursor cursor) {
    convertCursorToTransactionInfoList(cursor);
    adapter.setData(adapterData);
    adapter.notifyDataSetChanged();
    adapter.transactionData.notifyAll();
}
}

AdapterTransactions.java:

public class AdapterTransactions extends RecyclerView.Adapter<AdapterTransactions.MyViewHolder> {

private LayoutInflater inflater;
List<TransactionInfo> transactionData = Collections.emptyList();

public void setData(List<TransactionInfo> newData) {
    transactionData = newData;
}

public AdapterTransactions(Context context, List<TransactionInfo> transactionData) {
    inflater = LayoutInflater.from(context);
    this.transactionData = transactionData;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = inflater.inflate(R.layout.transaction_row, parent, false);
    MyViewHolder holder = new MyViewHolder(view);
    return holder;
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    TransactionInfo current = transactionData.get(position);
    holder.itemName.setText(current.itemName);
    holder.itemCat.setText(current.itemCat);
    holder.itemPrice.setText(current.itemPrice);
    holder.itemDate.setText(current.date);
    holder.itemCurrency.setText(current.itemCurrency);
}

@Override
public int getItemCount() {
    return transactionData.size();
}

class MyViewHolder extends RecyclerView.ViewHolder {
    TextView itemName, itemCat, itemPrice, itemDate, itemCurrency;

    public MyViewHolder(View itemView) {
        super(itemView);
        itemName = (TextView) itemView.findViewById(R.id.itemName);
        itemCat = (TextView) itemView.findViewById(R.id.itemCat);
        itemPrice = (TextView) itemView.findViewById(R.id.itemPrice);
        itemDate = (TextView) itemView.findViewById(R.id.itemDate);
        itemCurrency = (TextView) itemView.findViewById(R.id.itemCurrency);
    }
}
}

TransactionInfo.java:

public class TransactionInfo {
public String itemName, itemPrice, itemCurrency, itemCat, date;
}

RE ANSWERS:

I've tried the following method alterations to convertCursorToTransactionInfoList :

private void convertCursorToTransactionInfoList(Cursor cursor) {
    if (cursor != null) {
        while (cursor.moveToNext()) {
            TransactionInfo returnListValue = new TransactionInfo();
            returnListValue.itemName = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_NAME));
            returnListValue.itemCat = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CATEGORY));
            returnListValue.itemCurrency = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CURRENCY));
            returnListValue.itemPrice = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_PRICE));
            returnListValue.date = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_DATE));
            adapterData.add(returnListValue);
        }
    }
}

and

private static void convertCursorToTransactionInfoList(Cursor cursor, ArrayList<TransactionInfo> adapterData) {
    if (cursor != null) {
        while (cursor.moveToNext()) {
            TransactionInfo returnListValue = new TransactionInfo();
            returnListValue.itemName = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_NAME));
            returnListValue.itemCat = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CATEGORY));
            returnListValue.itemCurrency = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CURRENCY));
            returnListValue.itemPrice = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_PRICE));
            returnListValue.date = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_DATE));
            adapterData.add(returnListValue);
        }
    }
}

with notifying adatpers like this:

@Override
public void transactionLoadComplete(Cursor cursor) {
    convertCursorToTransactionInfoList(cursor, adapterData);
    adapter.setData(adapterData);
    adapter.notifyDataSetChanged();
    adapter.transactionData.notifyAll();
}

Also, note taht I had to change List<TransactionInfo> adapterData = new ArrayList<>(); to ArrayList<TransactionInfo> adapterData = new ArrayList<>();

The more I look at this the more I think it has to do with ArrayList<> or List<> issues.

END EDIT

The problem lies with getting the data out of the Cursor , specifically here:

if (cursor.moveToFirst()) {
    for (int i = 10; i < cursor.getCount(); i++) {
        returnListValue.itemName = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_NAME));
        returnListValue.itemCat = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CATEGORY));
        returnListValue.itemCurrency = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CURRENCY));
        returnListValue.itemPrice = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_PRICE));
        returnListValue.date = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_DATE));
        returnList.add(returnListValue);
    }
}

Your code above moves the cursor to the first position ( cursor.moveToFirst() ) but after that the Cursor position doesn't change so your loop is executed cursor.getCount() times but it only operates on the first item in the cursor.

Instead, I would opt for a while loop instead of a for loop, like this:

// move cursor on to next position if available
while(cursor.moveToNext()) { 
    // More data is available so add it to the list
    // process data as before
}

EDIT 1

RE your comment - here's what I suggest changing.

Instead of:

adapterData = convertCursorToBudgetInfoList(cursor);

Either:

Option 1

convertCursorToBudgetInfoList remains a static method but now operates on the original adapterData reference.

convertCursorToBudgetInfoList(cursor, adapterData);

and change your method to:

private static void convertCursorToBudgetInfoList(Cursor cursor, ArrayList<TransactionInfo> adapterData) {

    if (cursor != null) {                         

        while (cursor.moveToNext()) { // note: no for loop ;-)
            TransactionInfo returnListValue = new TransactionInfo();
            returnListValue.itemName = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_NAME));
            returnListValue.itemCat = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CATEGORY));
            returnListValue.itemCurrency = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CURRENCY));
            returnListValue.itemPrice = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_PRICE));
            returnListValue.date = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_DATE));
            adapterData.add(returnListValue);
        }
    }
}

Option 2

Make convertCursorToBudgetInfoList a member method instead of static and operate on your adapterData directly.

convertCursorToBudgetInfoList(cursor);

and change your method to:

private void convertCursorToBudgetInfoList(Cursor cursor) {

    if (cursor != null) {                         

        while (cursor.moveToNext()) { // note: no for loop ;-)
            TransactionInfo returnListValue = new TransactionInfo();
            returnListValue.itemName = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_NAME));
            returnListValue.itemCat = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CATEGORY));
            returnListValue.itemCurrency = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_CURRENCY));
            returnListValue.itemPrice = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_PRICE));
            returnListValue.date = cursor.getString(cursor.getColumnIndex(DatabaseHelper.TRANSACTION_DATE));
            adapterData.add(returnListValue); // member variable (same as this.adapterData)
        }
    }
}

Of course, with either of these options make sure to notify your adapter.

I would also reiterate that you really need to get rid of that for loop - step through it with a debugger and all will become clear.

Try changing this for loop within convertCursorToBudgetInfoList :

for (int i = 10; i < cursor.getCount(); i++) 

to start at 0 ... if there are less than 10 results nothing will show up!

The problem lies in TransactionsTab. In the transactionLoadComplete(Cursor cursor) method you update the Fragments List transactionData but you never pass this onto your RecyclerView Adapter. So calling notify on your adapter does nothing as it's data hasn't changed.

Your solution would be to create a function in your Adapter such as:

public void setData(List<TransactionData> newData){
    transactionData = newData;
}

Then call the new function before notifyDataSetChanged in transactionLoadComplete(Cursor cursor):

public void transactionLoadComplete(Cursor cursor) {
    adapterData = convertCursorToBudgetInfoList(cursor);
    adapter.setData(adapterData);
    adapter.notifyDataSetChanged();
    adapter.transactionData.notifyAll();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM