-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add load image uri and make item layout responsive #24
add load image uri and make item layout responsive #24
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one of the reasons why we set the image type to Drawable is we want to giving flexibilities to users to choose which library they use, like Picasso or Glide. do you remember that? @gifff @zainfikrih
gridmenuview/src/androidTest/java/com/bcc/gridmenuview/MenuItemTest.java
Outdated
Show resolved
Hide resolved
void bind(final MenuItem menuItem, boolean isImageUri) { | ||
title.setText(menuItem.getTitle()); | ||
if (isImageUri) { | ||
String toHttpsUri = menuItem.getImageUri().replace("http://","https://"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you think, should we replace http to https? which better, throw an exception to giving error message or just replace like this? @zainfikrih @gifff
Basically the issue with this implementation is that it's not scalable when you want to add more kind of image source (example: you want to load the image from local file path). One way to solve the issue is to use generic for Something like this: public class MenuItem<T> {
private String title;
private T imageSource;
public MenuItem(String title, T imageSource){
this.title = title;
this.imageSource = imageSource;
}
public String getTitle() {
return title;
}
public T getImageSource() {
return imageSource;
}
} and then for the adapter, you do something like this: class ViewHolder extends RecyclerView.ViewHolder {
// ...
void bind(final MenuItem<?> menuItem) {
title.setText(menuItem.getTitle());
RequestManager glideRequest = Glide.with(itemView);
RequestBuilder<Drawable> glideRequestBuilder = null;
if (menuItem.getImageSource() instanceof String) {
glideRequestBuilder = glideRequest.load(menuItem.getImageSource());
} else if (menuItem.getImageSource() instanceof Uri) {
glideRequestBuilder = glideRequest.load(menuItem.getImageSource());
} else if (menuItem.getImageSource() instanceof Drawable) {
glideRequestBuilder = glideRequest.load(menuItem.getImageSource());
} else if (menuItem.getImageSource() instanceof Bitmap) {
glideRequestBuilder = glideRequest.load(menuItem.getImageSource());
}
if (glideRequestBuilder != null) {
glideRequestBuilder.into(image);
}
imageOverlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (gridMenuOnClickListener != null) {
gridMenuOnClickListener.onClick(getAdapterPosition());
}
}
});
}
} and the list will look like: final ArrayList<MenuItem<?>> list = new ArrayList<>();
list.add(new MenuItem<>("satu", getResources().getDrawable(R.drawable.ic_launcher_background)));
list.add(new MenuItem<>("dua", getResources().getDrawable(R.drawable.ic_launcher_background)));
list.add(new MenuItem<>("lima", "https://cdn3.iconfinder.com/data/icons/capsocial-round/500/youtube3-128.png"));
list.add(new MenuItem<>("enam","https://cdn3.iconfinder.com/data/icons/capsocial-round/500/facebook-128.png")); However, this library will be heavily dependent on Glide and give the users no flexibility to choose their own image loader library. |
Thanks for the input mas gif, i'll edit the MenuItem to Generic Types. |
@gifff solutions is also good, but if we want to add another image source type, it will require many changes on I was thought bout another solutions, we can wrap ImageSource using contract something like this. This is will give us flexibilty to decide what source that can be use to make a drawable: interface ImageProvider {
Drawable getDrawable();
}
public class MenuItem {
private String title;
private ImageProvider imageProvider;
public MenuItem(String title, ImageProvider imageProvider){
this.title = title;
this.imageProvider = imageProvider;
}
public String getTitle() {
return title;
}
public Drawable getDrawable() {
return imageProvider.getDrawable();
}
}
class NetworkImageProvider implements ImageProvider {
private URL url;
NetworkImageProvider(URL url) {
this.url = url;
}
Drawable getDrawable() {
// return drawable from url
}
}
class LocalImageProvider implements ImageProvider {
private String filePath;
LocalImageProvider(String filePath) {
this.filePath = filePath;
}
Drawable getDrawable() {
// return drawable from filepath
}
}
class AnotherImageProvider implements ImageProvider {
Drawable getDrawable() {
// whaterver you want
}
} Example: NetworkImageProvider np = new NetworkImageProvider("https://foo.com/image.jpg");
LocalImageProvider lp = new LocalImageProvider("/media/imgs/kuda.jpg");
MenuItem item = new MenuItem("Foo", np);
MenuItem kuda = new MenuItem("Kuda", lp); wdyt? |
Fair enough. But if we could make the image loading system pluggable, isn't it better to let the user configure the loading implementation (such as caching, transformation, etc.) ?
About this, I think we should leave the choices to the user. It will reduce the chance of unexpected behaviour in the user side. @99ridho To me, it is an elegant solution 👍 |
@radityarin yes please redesign like @99ridho suggestion, I agree with that to make this project scalable |
@adityapp speaking of which, this redesign is going to make current test not working, because the changes in the model MenuItem, what should i do? is it fine if i delete it first or should i edit it? thanks. |
i think refactoring is also modify the test too |
yes, if you change the contract you should change the test also |
…Drawable, Local, and Network drawable that implements ImageProvider
public MenuItem(String title, Drawable image){ | ||
public MenuItem(String title, ImageProvider imageProvider) { | ||
this.title = title; | ||
this.image = image; | ||
this.imageProvider = imageProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we keep the previous constructor? That way, we don't introduce breaking-change to the previous users.
Do something like this:
public MenuItem(String title, Drawable image) {
this(title, new DrawableImageProvider(image));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added mas @gifff , please check, thanks.
@@ -2,7 +2,7 @@ | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:id="@+id/square_layout" | |||
android:orientation="vertical" | |||
android:layout_width="wrap_content" | |||
android:layout_width="match_parent" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, why this is changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Cool 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good jobs man, Thank you 🍻
@@ -13,4 +13,5 @@ | |||
android:layout_height="wrap_content" | |||
android:layout_margin="16dp" | |||
app:spanCount="4" /> | |||
|
|||
</LinearLayout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add newlines after last tag
@SuppressLint("StaticFieldLeak") | ||
private Context context; | ||
|
||
public LocalImageTask(ImageProvider imageProvider, Context context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think will be better if you put context in first params to be consistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question tho, why use @SuppressLint("StaticFieldLeak")
on line 17? it just suppress the warning about the possibility of memory leaked given inside AS 🤔 . Adding WeekReference<Context>
would be great solution i guess
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks mas andri for the input, should i make a new pull request of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeeep, it would be great broo @radityarin
cc: @gifff @adityapp
@SuppressLint("StaticFieldLeak") | ||
private Context context; | ||
|
||
public NetworkImageTask(ImageProvider imageProvider, Context context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will be better if the first param is context
thanks for the review, i switched the parameter position, thanks mas @adityapp . |
add load image uri and make item layout responsive (bccfilkom#24)
i try to add load image uri and make item layout responsive, please check @adityapp @gifff @zainfikrih
thanks.