ListFragment / CursorAdapter Showing Empty (No Dat

2019-07-04 04:12发布

问题:

I am unable to get my listview to display my data, it only shows the empty/no data textview.

I have been trying to solve this one for a while, scoured stackoverflow and the net.

Tried lots of different things.

Logcat shows that my newView/bindView is not getting called/reached.

I think that it is either an error in my XML layout (my CursorAdapter doesn't know to inflate my row layout/view).

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >

    <!-- <include layout="@layout/fragment_data_table_header" />  -->

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1.0"
        android:orientation="vertical">
    </ListView>

    <TextView
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="No Data"
        android:textColor="@color/accent"
        android:textSize="@dimen/text_xlarge" />

</LinearLayout>

Or I'm calling the setListAdapter incorrectly (or using the wrong imports?), since my cursor test shows it has the data.

package au.id.teda.broadband.usage.ui.fragments;

import com.actionbarsherlock.app.SherlockListFragment;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import au.id.teda.broadband.usage.R;
import au.id.teda.broadband.usage.authenticator.AccountAuthenticator;
import au.id.teda.broadband.usage.cursoradapter.DailyDataTableCursorAdapter;
import au.id.teda.broadband.usage.database.DailyDataDatabaseAdapter;
import au.id.teda.broadband.usage.helper.AccountInfoHelper;
import au.id.teda.broadband.usage.helper.AccountStatusHelper;
import au.id.teda.broadband.usage.ui.MainActivity;

public class DataTableFragment extends SherlockListFragment {

    // Debug tag pulled from main activity
    private final static String DEBUG_TAG = MainActivity.DEBUG_TAG;

    // View inflated by fragment
    private View mFragmentView;

    // Helper classes
    private AccountInfoHelper mAccountInfo;
    private AccountStatusHelper mAccountStatus;
    private AccountAuthenticator mAccountAuthenticator;

    // Receive sync broadcasts
    private SyncReceiver mSyncReceiver;
    private IntentFilter filter;

    // Activity context to be used
    private Context mContext;

    /**
     * Called 1st in the fragment life cycle
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Load helper classes
        mAccountInfo = new AccountInfoHelper(activity);
        mAccountStatus = new AccountStatusHelper(activity);
        mAccountAuthenticator = new AccountAuthenticator(activity);
    }

    /**
     * Called 2nd in the fragment life cycle
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set context for fragment. 
        // Activity extends context so we get it from there
        mContext = getActivity();

        // Setup broadcast receiver for background sync
        String BROADCAST = getString(R.string.sync_broadcast_action);
        filter = new IntentFilter(BROADCAST);
        mSyncReceiver = new SyncReceiver();
    }

    /**
     * Called 3rd in the fragment life cycle
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Set fragment layout to be inflated
        mFragmentView = inflater.inflate(R.layout.fragment_data_table, container, false);

        return mFragmentView;
    }

    /**
     * Called 4th in the fragment life cycle
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        DailyDataDatabaseAdapter mDatabase = new DailyDataDatabaseAdapter(mContext);
        mDatabase.open();

        String period = mAccountStatus.getDataBaseMonthString();
        //Log.d(DEBUG_TAG, "Period to query database:" + period);

        Cursor cursor = mDatabase.getPriodUsageCursor(period);
        Log.d(DEBUG_TAG, "Cursor Length:" + cursor.getCount());

        DailyDataTableCursorAdapter adapter = new DailyDataTableCursorAdapter(mContext, cursor, true);
        //adapter.testCursor(cursor);

        setListAdapter(adapter);
        //cursor.close();
        mDatabase.close();
    }

    /**
     * Called 5th in the fragment life cycle
     */
    @Override
    public void onResume() {
        super.onResume();

        // Register broadcast receiver for background sync
        getActivity().registerReceiver(mSyncReceiver, filter);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Log.d(DEBUG_TAG, "Item clicked: " + id);
    }

    /**
     * First call in the death of fragment
     */
    @Override
    public void onPause() {
        super.onPause();

        // Unregister broadcast receiver for background sync
        getActivity().unregisterReceiver(mSyncReceiver);
    }

    public class SyncReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent i) {

            String MESSAGE = getString(R.string.sync_broadcast_message);
            String SYNC_START = getString(R.string.sync_broadcast_start);
            String SYNC_COMPLETE = getString(R.string.sync_broadcast_complete);

            String msg = i.getStringExtra(MESSAGE);
            if (msg.equals(SYNC_START)){
                // Nothing to see here move along
            } else if (msg.equals(SYNC_COMPLETE)){
            }
        }

    }

}

Or my CursorAdapter constructor is wrong? So it doesn't know to start inflating and binding the views/rows

package au.id.teda.broadband.usage.cursoradapter;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import au.id.teda.broadband.usage.R;
import au.id.teda.broadband.usage.database.DailyDataDatabaseAdapter;
import au.id.teda.broadband.usage.ui.MainActivity;

public class DailyDataTableCursorAdapter extends CursorAdapter {

    private final static String DEBUG_TAG = MainActivity.DEBUG_TAG;

    private LayoutInflater mLayoutInflater;
    private Cursor mCursor;
    private Context mContext;

    private int COLUMN_INDEX_DAY;
    private int COLUMN_INDEX_PEAK;
    private int COLUMN_INDEX_OFFPEAK;
    private int COLUMN_INDEX_UPLOADS;
    private int COLUMN_INDEX_FREEZONE;

    private int count;

    private int GB = 1000000;

    public DailyDataTableCursorAdapter(Context context, Cursor cursor, boolean autoRequery) {
        super(context, cursor, autoRequery);
        Log.d(DEBUG_TAG, "DailyDataCursorAdapter");

        this.mContext = context;
        this.mCursor = cursor;
        this.mLayoutInflater = LayoutInflater.from(context);

        this.COLUMN_INDEX_DAY = mCursor.getColumnIndex(DailyDataDatabaseAdapter.DAY);
        this.COLUMN_INDEX_PEAK = mCursor.getColumnIndex(DailyDataDatabaseAdapter.PEAK);
        this.COLUMN_INDEX_OFFPEAK = mCursor.getColumnIndex(DailyDataDatabaseAdapter.OFFPEAK);
        this.COLUMN_INDEX_UPLOADS = mCursor.getColumnIndex(DailyDataDatabaseAdapter.UPLOADS);
        this.COLUMN_INDEX_FREEZONE = mCursor.getColumnIndex(DailyDataDatabaseAdapter.FREEZONE);

    }

    @Override
    public int getCount() {
        return count;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    /**

    private final class ViewHolder {
        public TextView day;
        public TextView peak;
        public TextView offpeak;
        public TextView uploads;
        public TextView freezone;
        public TextView total;
        public TextView accum;
    }


    @Override
    public View getView(int position, View view, ViewGroup parent) {

        Log.d(DEBUG_TAG, "DailyDataCursorAdapter.getView()");

        if (mCursor.moveToPosition(position)) {
            ViewHolder holder;

            if (view == null) {
                view = mLayoutInflater.inflate(R.layout.fragment_data_table_row, null);

                holder = new ViewHolder();
                holder.day = (TextView) view.findViewById(R.id.fragment_data_table_row_date);
                holder.peak = (TextView) view.findViewById(R.id.fragment_data_table_row_peak);
                holder.offpeak = (TextView) view.findViewById(R.id.fragment_data_table_row_offpeak);
                holder.uploads = (TextView) view.findViewById(R.id.fragment_data_table_row_uploads);
                holder.freezone = (TextView) view.findViewById(R.id.fragment_data_table_row_freezone);
                holder.total = (TextView) view.findViewById(R.id.fragment_data_table_row_total);
                holder.accum  = (TextView) view.findViewById(R.id.fragment_data_table_row_accum);


                view.setTag(holder);
            }
            else {
                holder = (ViewHolder) view.getTag();
            }

            String day = LongDateToString(mCursor.getLong(COLUMN_INDEX_DAY), "dateOfMouth");
            String peak = IntUsageToString(mCursor.getLong(COLUMN_INDEX_PEAK));
            String offpeak = IntUsageToString(mCursor.getLong(COLUMN_INDEX_OFFPEAK));
            String uploads = IntUsageToString(mCursor.getLong(COLUMN_INDEX_UPLOADS));
            String freezone = IntUsageToString(mCursor.getLong(COLUMN_INDEX_FREEZONE));
            String total = IntUsageToString( mCursor.getLong(COLUMN_INDEX_PEAK)
                    + mCursor.getLong(COLUMN_INDEX_OFFPEAK) );

            Log.d(DEBUG_TAG, "day:" + day);
            Log.d(DEBUG_TAG, "peak:" + peak);
            Log.d(DEBUG_TAG, "offpeak:" + offpeak);
            Log.d(DEBUG_TAG, "uploads:" + uploads);
            Log.d(DEBUG_TAG, "freezone:" + freezone);
            Log.d(DEBUG_TAG, "totalUsageLong:" + total);

            holder.day.setText(day);
            holder.peak.setText(peak);
            holder.offpeak.setText(offpeak);
            holder.uploads.setText(uploads);
            holder.freezone.setText(freezone);
            holder.total.setText(total);
        }

        return view;
    }
    **/

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        Log.d(DEBUG_TAG, "DailyDataCursorAdapter.newView()");
        // Inflate the list view with the changes above
        View view = mLayoutInflater.inflate(R.layout.fragment_data_table_row, parent, false);
        return view;
    }

    @Override
    public void bindView(View row, Context context, Cursor cursor) {
        Log.d(DEBUG_TAG, "DailyDataCursorAdapter.bindView()");
        // Set usage text views
        TextView dateTV = (TextView) row.findViewById(R.id.fragment_data_table_row_date);
        TextView peakTV = (TextView) row.findViewById(R.id.fragment_data_table_row_peak);
        TextView offpeakTV = (TextView) row.findViewById(R.id.fragment_data_table_row_offpeak);
        TextView uploadTV = (TextView) row.findViewById(R.id.fragment_data_table_row_uploads);
        TextView freezoneTV = (TextView) row.findViewById(R.id.fragment_data_table_row_freezone);
        TextView totalTV = (TextView) row.findViewById(R.id.fragment_data_table_row_total);
        TextView accumTV = (TextView) row.findViewById(R.id.fragment_data_table_row_accum);

        // Set variables and pull data from database cursor
        // TODO: Change DailyDataDBAdapter to dailyDataDBHelper???
        long day = cursor.getLong(COLUMN_INDEX_DAY);
        long peak = cursor.getLong(COLUMN_INDEX_PEAK);
        long offpeak = cursor.getLong(COLUMN_INDEX_OFFPEAK);
        long uploads = cursor.getLong(COLUMN_INDEX_UPLOADS);
        long freezone = cursor.getLong(COLUMN_INDEX_FREEZONE);
        long total = (peak + offpeak);

        Log.d(DEBUG_TAG, "day:" + day);
        Log.d(DEBUG_TAG, "peak:" + peak);
        Log.d(DEBUG_TAG, "offpeak:" + offpeak);
        Log.d(DEBUG_TAG, "uploads:" + uploads);
        Log.d(DEBUG_TAG, "freezone:" + freezone);
        Log.d(DEBUG_TAG, "total:" + total);

        dateTV.setText(LongDateToString(day, "dateOfMouth"));
        peakTV.setText(IntUsageToString(peak));
        offpeakTV.setText(IntUsageToString(offpeak));
        uploadTV.setText(IntUsageToString(uploads));
        freezoneTV.setText(IntUsageToString(freezone));
        totalTV.setText(IntUsageToString(total));

    }

    public void testCursor(Cursor cursor){

        cursor.moveToFirst();
        if (cursor != null){
            while (cursor.moveToNext()){

                long day = cursor.getLong(COLUMN_INDEX_DAY);
                long peak = cursor.getLong(COLUMN_INDEX_PEAK);
                long offpeak = cursor.getLong(COLUMN_INDEX_OFFPEAK);
                long uploads = cursor.getLong(COLUMN_INDEX_UPLOADS);
                long freezone = cursor.getLong(COLUMN_INDEX_FREEZONE);
                long total = (peak + offpeak);

                Log.d(DEBUG_TAG, "dateLong:" + day);
                Log.d(DEBUG_TAG, "peakUsageLong:" + peak);
                Log.d(DEBUG_TAG, "offpeakUsageLong:" + offpeak);
                Log.d(DEBUG_TAG, "uploadUsageLong:" + uploads);
                Log.d(DEBUG_TAG, "freezoneUsageLong:" + freezone);
                Log.d(DEBUG_TAG, "totalUsageLong:" + total);

            }
            cursor.close();
        }
    }

    // Return string values for date long millisec stored in db
    private String LongDateToString(long millisecs, String convertTo) {
        DateFormat date_format = null;
        if (convertTo == "dayOfWeek") {
            date_format = new SimpleDateFormat("EEE");
        } else if (convertTo == "dateOfMouth"){
            date_format = new SimpleDateFormat("dd");
        } else if (convertTo == "mouthOfYear"){
            date_format = new SimpleDateFormat("MMM");
        }
        Date resultdate = new Date(millisecs);
        return date_format.format(resultdate);
    }

    // Return formated string value for int stored in db
    private String IntUsageToString (long usage){
        NumberFormat numberFormat = new DecimalFormat("#,###");
        return numberFormat.format(usage/GB);

    }

}

Any help/suggestions would be appreciated.