Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding Cursor data to a non-list layout

I'm writing a screen that displays a row's worth of information from a DB. Basically it's a Detail Fragment that represents information pertaining to one 'row' in a table. I want to understand the best practice for binding data from a cursor (one unique row from a table) to a layout of textviews, checkboxes, etc.

Is AdapterView the ticket?

@JoeMalin suggested:

Then write an adapter between a cursor and an array of text views.

Which boils down my question. What's the right way to hook a series of text views to a cursor?

like image 803
Joel Skrepnek Avatar asked Nov 13 '22 10:11

Joel Skrepnek


2 Answers

If you want to do processing on some of the cursor data before you move it to the text views, then you're going beyond the adapter pattern, which assumes that "recasting" the form of a data structure to another data structure without any intermediate processing. The virtue of an adapter is that, for two data structures A and B linked by an adapter, it's assumed that B automatically changes whenever A changes.

Of course, you can redefine the idea of adapter to insert your own intermediate operation, such as converting dates, or you could make the conversion an aspect of the view that's displaying the data. I am guessing that the "processing" is really formatting, which you do for display purposes. That's an attribute of the text view, not the data; write something that extends text view and converts dates as needed. Then write an adapter between a cursor and an array of text views.

like image 107
Joe Malin Avatar answered Nov 16 '22 03:11

Joe Malin


I recently implemented my own data adapter class that may be in the ball park.

public class NoteImageDataAdapter {

private final View mMainView;
private Cursor mCursor;
private ViewHolder holder;
private ContentObserver mContentObserver;

public static class ViewHolder {
    public TextView title;
    public TextView text;
    public ImageView image;
}

public NoteImageDataAdapter(View mainView, Cursor c) {
    if (mainView == null) {
        throw new IllegalArgumentException("View mainView cannot be null");
    }

    if (c == null) {
        throw new IllegalArgumentException("Cursor c cannot be null");
    }
    mMainView = mainView;
    mCursor = c;

    holder = new ViewHolder();
    holder.title = (TextView) mMainView.findViewById(R.id.title);
    holder.text = (TextView) mMainView.findViewById(R.id.text);
    holder.image = (ImageView) mMainView.findViewById(R.id.myImageView);

    mContentObserver = new ImageNoteContentObserver(new Handler());
    mCursor.registerContentObserver(mContentObserver);
    bindView();
}

class ImageNoteContentObserver extends ContentObserver {

    public ImageNoteContentObserver(Handler handler) {
        super(handler);
    }

    @Override
    public boolean deliverSelfNotifications() {
        return true;
    }

    @Override
    public void onChange(boolean selfChange) {
        Log.d("NoteImageDataAdapter", "ImageNoteContentObserver.onChange( "
                + selfChange + ")");
        super.onChange(selfChange);
        mCursor.requery();
        bindView();
    }
}

public void bindView() {
    Log.d("NoteImageDataAdapter", "bindView");
    mCursor.moveToFirst();

    holder.text.setText(Note.getText(mCursor));
    holder.title.setText(Note.getTitle(mCursor));

    Uri imageUri = Note.getImageUri(mCursor);
    if (imageUri != null) {
        assignImage(holder.image, imageUri);
    } else {
        Drawable d = Note.getImageThumbnail(mCursor);
        holder.image.setImageDrawable(d);
        holder.image.setVisibility(View.VISIBLE);
    }
}

private static final int MAX_IMAGE_PIXELS = 1024*512;

private void assignImage(ImageView imageView, Uri imageUri){
    if (imageView != null && imageUri != null){

        ContentResolver cr = imageView.getContext().getContentResolver();

        Display display = ((WindowManager) imageView.getContext()
                .getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        int width = (int) (display.getWidth() * 0.9);
        int height = (int) (display.getHeight() * 0.9);

        int minSideLength = Math.min(height, width);

        Bitmap b = Util.makeBitmap(minSideLength, MAX_IMAGE_PIXELS, imageUri, cr, false);

        if (b == null){
            b = Util.makeBitmap(minSideLength, MAX_IMAGE_PIXELS/2, imageUri, cr, false);                
        }
        if (b != null){
            imageView.setImageBitmap(b);
            imageView.setAdjustViewBounds(true);
            imageView.setVisibility(View.VISIBLE);
        }   
    }   
}

}

and in your activity

private NoteImageDataAdapter mAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.note_image_view_layout);

    wireDataAdapter();       
}

private void wireDataAdapter() {
    final String[] COLUMNS = new String[] { 
            Note.Columns.TITLE,
            Note.Columns.TEXT,
            Note.Columns.IMAGE_URI, 
            Note.Columns.IMAGE_THUMBNAIL,
            Note.Columns._ID };

    // the uri for the note row
    Uri contentUri = getIntent().getData();
    Cursor cur = managedQuery(contentUri, COLUMNS, null, null, null);

    View mainLayout = this.findViewById(R.id.noteImageViewLayout);
    mAdapter = new NoteImageDataAdapter(mainLayout, cur);
}
like image 27
John N Avatar answered Nov 16 '22 03:11

John N