Skip to content

Instantly share code, notes, and snippets.

@jayrambhia
Last active June 24, 2017 12:09
Show Gist options
  • Save jayrambhia/cd0e65e1b24f45d2bb05a790e812468a to your computer and use it in GitHub Desktop.
Save jayrambhia/cd0e65e1b24f45d2bb05a790e812468a to your computer and use it in GitHub Desktop.
GIF search engine with Litho and Giphy for Android
public class GifItem {
private final String id;
private final String image;
public GifItem(JsonObject json) {
this.id = json.get("id").getAsString();
JsonObject image = json.get("images").getAsJsonObject().get("original").getAsJsonObject();
this.image = image.get("url").getAsString();
}
public String getId() {
return id;
}
public String getImage() {
return image;
}
}
@LayoutSpec
public class GifItemViewSpec {
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext c, @Prop String title) {
return Column.create(c)
.paddingDip(ALL, 16)
.backgroundColor(Color.WHITE)
.child(
Text.create(c)
.text(title)
.textSizeSp(40))
.build();
}
}
@MountSpec
public class GifItemViewSpec {
@OnMeasure
protected static void onMeasure(ComponentContext c, ComponentLayout layout, int widthSpec, int heightSpec, Size size) {
MeasureUtils.measureWithDesiredPx(widthSpec, heightSpec, 48*3, 48*3, size);
}
@OnCreateMountContent
protected static ImageView onCreateMountContent(ComponentContext c) {
ImageView view = new ImageView(c.getBaseContext());
view.setBackgroundColor(Color.WHITE);
view.setScaleType(ImageView.ScaleType.CENTER);
view.setImageResource(R.mipmap.ic_launcher);
return view;
}
}
@MountSpec
public class GifItemViewSpec {
@OnMeasure
protected static void onMeasure(ComponentContext c, ComponentLayout layout, int widthSpec, int heightSpec, Size size) {
MeasureUtils.measureWithAspectRatio(widthSpec, heightSpec, 1, size);
}
@OnCreateMountContent
protected static ImageView onCreateMountContent(ComponentContext c) {
ImageView view = new ImageView(c.getBaseContext());
view.setBackgroundColor(Color.WHITE);
view.setScaleType(ImageView.ScaleType.CENTER);
return view;
}
@OnMount
static void onMount(ComponentContext c, ImageView view, @Prop RequestManager glide, @Prop GifItem gif) {
Glide.with(c.getBaseContext()).load(gif.getImage()).asGif().into(view);
}
}
@LayoutSpec(events = { LikeChangeEvent.class })
public class GifItemViewSpec {
@OnCreateInitialState
static void createInitialState(ComponentContext c, StateValue<Boolean> isLiked, @Prop boolean initLiked) {
isLiked.set(initLiked);
}
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext context, @Prop GifItem gif,
@Prop RequestManager glide, @State boolean isLiked) {
... create component view here
}
@OnUpdateState
static void updateLikeButton(StateValue<Boolean> isLiked, @Param boolean updatedValue) {
isLiked.set(updatedValue);
}
@OnEvent(ClickEvent.class)
static void onLikeButtonClicked(ComponentContext c, @State boolean isLiked, @Prop GifItem gif) {
GifItemView.dispatchLikeChangeEvent(GifItemView.getLikeChangeEventHandler(c), !isLiked, gif.getId());
GifItemView.updateLikeButtonAsync(c, !isLiked);
}
@OnEvent(FavChangeEvent.class)
static void onFavChanged(ComponentContext c, @FromEvent boolean isLiked, @FromEvent String gifId, @Prop GifItem gif) {
if (gif.getId().equals(gifId)) {
// This will invoke updateLikeButton which will update isLiked state.
GifItemView.updateLikeButtonAsync(c, isLiked);
}
}
... some more stuff
public interface GifCallback {
void onGifSelected(GifItem gif, Component gifComponent);
}
}
@LayoutSpec
public class GifItemViewSpec {
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext c) {
return Column.create(c)
.paddingDip(ALL, 16)
.backgroundColor(Color.WHITE)
.child(
Text.create(c)
.text("Hello world")
.textSizeSp(40))
.build();
}
}
@LayoutSpec
public class HomeComponentSpec {
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext c, @Prop String hint, @Prop RecyclerBinder binder) {
return Column.create(c)
.paddingDip(YogaEdge.ALL, 8)
.child(getEditTextComponent(c, hint))
.child(getRecyclerComponent(c, binder))
.build();
}
private static Component<EditText> getEditTextComponent(ComponentContext c, String hint) {
return EditText.create(c)
.textSizeDip(16)
.hint(hint)
.build();
}
private static Component<Recycler> getRecyclerComponent(ComponentContext c, RecyclerBinder binder) {
return Recycler.create(c).binder(binder).build();
}
}
@LayoutSpec
public class HomeComponentSpec {
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext c, @Prop String hint, @Prop RecyclerBinder binder) {
return Column.create(c)
.paddingDip(YogaEdge.ALL, 8)
.child(getEditTextComponent(c, hint))
.child(getRecyclerComponent(c, binder))
.build();
}
private static Component<EditText> getEditTextComponent(ComponentContext c, String hint) {
return EditText.create(c)
.textSizeDip(16)
.hint(hint)
.textChangedEventHandler(HomeComponent.onQueryChanged(c))
.build();
}
@OnEvent(TextChangedEvent.class)
static void onQueryChanged(ComponentContext c, @Prop OnQueryUpdateListener listener, @FromEvent String text) {
listener.onQueryUpdated(text);
}
private static Component<Recycler> getRecyclerComponent(ComponentContext c, RecyclerBinder binder) {
return Recycler.create(c).binder(binder).build();
}
public interface OnQueryUpdateListener {
void onQueryUpdated(String query);
}
}
private static Component<Recycler> getRecyclerComponent(ComponentContext c) {
RecyclerBinder binder = new RecyclerBinder(c, new LinearLayoutInfo(c.getBaseContext(), OrientationHelper.VERTICAL, false));
for (int i=0; i<20; i++) {
binder.insertItemAt(i, ComponentInfo.create().component(
GifItemView.create(c)
.title("Hello, " + i)
.build()
));
}
return Recycler.create(c).binder(binder).build();
}
private static Component<Recycler> getRecyclerComponent(ComponentContext c) {
RecyclerBinder binder = new RecyclerBinder(c, new LinearLayoutInfo(c.getBaseContext(), OrientationHelper.VERTICAL, false));
for (int i=0; i<20; i++) {
binder.insertItemAt(i, ComponentInfo.create().component(GifItemView.create(c).build()));
}
return Recycler.create(c).binder(binder).build();
}
@LayoutSpec
public class HomeComponentSpec {
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext c, @Prop String hint) {
return Column.create(c)
.paddingDip(YogaEdge.ALL, 8)
.child(getEditTextComponent(c, hint))
.child(getRecyclerComponent(c))
.build();
}
private static Component<EditText> getEditTextComponent(ComponentContext c, String hint) {
return EditText.create(c)
.textSizeDip(16)
.hint(hint)
.build();
}
private static Component<Recycler> getRecyclerComponent(ComponentContext c) {
RecyclerBinder binder = new RecyclerBinder(c, new LinearLayoutInfo(c.getBaseContext(), OrientationHelper.VERTICAL, false));
return Recycler.create(c).binder(binder).build();
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext c = new ComponentContext(this);
final RecyclerBinder binder = new RecyclerBinder(c, new LinearLayoutInfo(c.getBaseContext(),
OrientationHelper.VERTICAL, false));
final Component component = HomeComponent.create(c)
.hint("Search Gif")
.binder(binder)
.build();
final LithoView view = LithoView.create(this, component);
setContentView(view);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
for (int i=0; i<20; i++) {
binder.insertItemAt(i, ComponentInfo.create().component(
GifItemView.create(c)
.title("Hello, " + i)
.build()
));
}
}
}, 2000);
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext c = new ComponentContext(this);
final RecyclerBinder binder = new RecyclerBinder(c, new RecyclerBinder(c, new GridLayoutInfo(this, 3));
final RequestManager glide = Glide.with(this);
final GifProvider gifProvider = new GifProvider(new GifProvider.ResposneListener() {
@Override
public void onSuccess(List<GifItem> gifs) {
updateContent(c, binder, glide, gifs);
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
final Component component = HomeComponent.create(c)
.hint("Search Gif")
.binder(binder)
.listener(new HomeComponentSpec.OnQueryUpdateListener() {
@Override
public void onQueryUpdated(String query) {
if (query.length() >= 6) {
gifProvider.search(query);
}
}
})
.build();
final LithoView view = LithoView.create(this, component);
setContentView(view);
}
private void updateContent(ComponentContext c, RecyclerBinder binder, List<GifItem> gifs) {
binder.removeRangeAt(0, binder.getItemCount());
List<ComponentInfo> components = new ArrayList<>();
for (GifItem gif: gifs) {
components.add(ComponentInfo.create().component(
GifItemView.create(c)
.gif(gif)
.key(gif.getId())
.build()
).build()
);
}
binder.insertRangeAt(0, components);
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Code here
final RecyclerBinder binder = new RecyclerBinder(c, new RecyclerBinder(c, new GridLayoutInfo(this, 3));
// More code here
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
for (int i=0; i<20; i++) {
binder.insertItemAt(i, ComponentInfo.create().component(
GifItemView.create(c)
.build()
));
}
}
}, 2000);
}
}
final Component component = HomeComponent.create(c)
.hint("Search Gif")
.binder(binder)
.listener(new HomeComponentSpec.OnQueryUpdateListener() {
@Override
public void onQueryUpdated(String query) {
Log.i("MainActivity", "query updated: " + query);
}
})
.build();
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ComponentContext c = new ComponentContext(this);
final Component component = HomeComponent.create(c)
.hint("Search Gif")
.build();
final LithoView view = LithoView.create(this, component);
setContentView(view);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment