/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.stetho.sample;
import java.io.IOException;
import android.app.ListActivity;
import android.app.LoaderManager;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.CharArrayBuffer;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/**
* Simple demonstration of fetching and caching a specific RSS feed showing the
* "Astronomy Picture of the Day" feed from NASA. This demonstrates both the database access
* and network inspection features of Stetho.
*/
public class APODActivity extends ListActivity {
private static final int LOADER_APOD_POSTS = 1;
private static final String TAG = "APODActivity";
private APODPostsAdapter mAdapter;
public static void show(Context context) {
context.startActivity(new Intent(context, APODActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(LOADER_APOD_POSTS, new Bundle(), mLoaderCallback);
new APODRssFetcher(getContentResolver()).fetchAndStore();
mAdapter = new APODPostsAdapter(this);
setListAdapter(mAdapter);
}
@Override
protected void onDestroy() {
super.onDestroy();
getLoaderManager().destroyLoader(LOADER_APOD_POSTS);
}
private final LoaderManager.LoaderCallbacks<Cursor> mLoaderCallback =
new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_APOD_POSTS:
return APODPostsQuery.createCursorLoader(APODActivity.this);
default:
throw new IllegalArgumentException("id=" + id);
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.changeCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
};
private class APODPostsAdapter extends CursorAdapter {
private final LayoutInflater mInflater;
public APODPostsAdapter(Context context) {
super(context, null /* cursor */, false /* autoRequery */);
mInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = mInflater.inflate(R.layout.apod_list_item, parent, false);
view.setTag(new ViewHolder(view));
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder)view.getTag();
int bindPosition = cursor.getPosition();
holder.position = bindPosition;
final String imageUrl = cursor.getString(APODPostsQuery.LARGE_IMAGE_URL_INDEX);
holder.image.setImageDrawable(null);
fetchImage(imageUrl, bindPosition, holder);
cursor.copyStringToBuffer(APODPostsQuery.TITLE_INDEX, holder.titleBuffer);
setTextWithBuffer(holder.title, holder.titleBuffer);
cursor.copyStringToBuffer(APODPostsQuery.DESCRIPTION_TEXT_INDEX, holder.descriptionBuffer);
setTextWithBuffer(holder.description, holder.descriptionBuffer);
}
// Really crude image handling. Please don't do this in a real app :)
private void fetchImage(
final String imageUrl,
final int bindPosition,
final ViewHolder holder) {
Networker.HttpRequest imageRequest = Networker.HttpRequest.newBuilder()
.method(Networker.HttpMethod.GET)
.url(imageUrl)
.build();
Networker.get().submit(imageRequest, new Networker.Callback() {
@Override
public void onResponse(Networker.HttpResponse result) {
if (bindPosition == holder.position) {
Log.d(TAG, "Got " + imageUrl + ": " + result.statusCode + ", " + result.body.length);
if (result.statusCode == 200) {
final Bitmap bitmap =
BitmapFactory.decodeByteArray(result.body, 0, result.body.length);
APODActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
holder.image.setImageDrawable(new BitmapDrawable(bitmap));
}
});
}
}
}
@Override
public void onFailure(IOException e) {
// Let Stetho demonstrate the errors :)
}
});
}
}
private static class ViewHolder {
public final ImageView image;
public final TextView title;
public final CharArrayBuffer titleBuffer = new CharArrayBuffer(32);
public final TextView description;
public final CharArrayBuffer descriptionBuffer = new CharArrayBuffer(64);
int position;
public ViewHolder(View v) {
image = (ImageView)v.findViewById(R.id.image);
title = (TextView)v.findViewById(R.id.title);
description = (TextView)v.findViewById(R.id.description);
}
}
private static void setTextWithBuffer(TextView textView, CharArrayBuffer buffer) {
textView.setText(buffer.data, 0, buffer.sizeCopied);
}
private static class APODPostsQuery {
public static String[] PROJECTION = {
APODContract.Columns._ID,
APODContract.Columns.TITLE,
APODContract.Columns.DESCRIPTION_TEXT,
APODContract.Columns.LARGE_IMAGE_URL,
};
public static final int ID_INDEX = 0;
public static final int TITLE_INDEX = 1;
public static final int DESCRIPTION_TEXT_INDEX = 2;
public static final int LARGE_IMAGE_URL_INDEX = 3;
public static CursorLoader createCursorLoader(Context context) {
return new CursorLoader(
context,
APODContract.CONTENT_URI,
PROJECTION,
null /* selection */,
null /* selectionArgs */,
null /* sortOrder */);
}
}
}