Browse Source

Replaced Volley library with Picasso.

pull/24/head
Apostolos Fanakis 8 years ago
parent
commit
73fa8091e4
  1. 2
      app/build.gradle
  2. 1
      app/src/main/AndroidManifest.xml
  3. 11
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  4. 82
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  5. 5
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
  6. 10
      app/src/main/java/gr/thmmy/mthmmy/data/Post.java
  7. 7
      app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
  8. 57
      app/src/main/java/gr/thmmy/mthmmy/utils/CircleTransform.java
  9. 72
      app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java
  10. 66
      app/src/main/java/gr/thmmy/mthmmy/utils/ImageController.java
  11. 41
      app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java
  12. 10
      app/src/main/res/layout/activity_topic_post_row.xml
  13. 3
      app/src/main/res/values/dimens.xml
  14. 2
      app/src/main/res/values/strings.xml
  15. 2
      build.gradle

2
app/build.gradle

@ -33,8 +33,8 @@ dependencies {
compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'org.jsoup:jsoup:1.10.1'
compile 'com.android.volley:volley:1.0.0'
compile 'com.github.franmontiel:PersistentCookieJar:v1.0.0'
compile('com.mikepenz:materialdrawer:5.8.0@aar') {
transitive = true

1
app/src/main/AndroidManifest.xml

@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:name=".utils.ImageController"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"

11
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -35,7 +35,6 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.BaseActivity;
import gr.thmmy.mthmmy.activities.LoginActivity;
import gr.thmmy.mthmmy.data.Post;
import gr.thmmy.mthmmy.utils.ImageController;
import okhttp3.Request;
import okhttp3.Response;
@ -68,13 +67,14 @@ public class TopicActivity extends BaseActivity {
private static final int LARGE_STEP = 10;
private Integer pageRequestValue;
ImageButton firstPage;
ImageButton previousPage;
ImageButton nextPage;
ImageButton lastPage;
private ImageButton firstPage;
private ImageButton previousPage;
private ImageButton nextPage;
private ImageButton lastPage;
//Other variables
private ProgressBar progressBar;
@SuppressWarnings("unused")
private static final String TAG = "TopicActivity";
private String topicTitle;
private FloatingActionButton replyFAB;
@ -187,7 +187,6 @@ public class TopicActivity extends BaseActivity {
@Override
protected void onDestroy() { //When finished cancel whatever request can still be canceled
super.onDestroy();
ImageController.getInstance().cancelPendingRequests();
}

82
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java

@ -7,6 +7,7 @@ import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@ -15,24 +16,23 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.volley.toolbox.ImageLoader;
import com.squareup.picasso.Picasso;
import java.util.List;
import java.util.Objects;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.data.Post;
import gr.thmmy.mthmmy.utils.CircularNetworkImageView;
import gr.thmmy.mthmmy.utils.ImageController;
import gr.thmmy.mthmmy.utils.CircleTransform;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.base_url;
@ -41,23 +41,22 @@ import static gr.thmmy.mthmmy.activities.topic.TopicActivity.toQuoteList;
class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
private static final String TAG = "TopicAdapter";
private static final int THUMBNAIL_SIZE = 80;
private ImageLoader imageLoader = ImageController.getInstance().getImageLoader();
private Context context;
private List<Post> postsList;
private static int THUMBNAIL_SIZE;
private final Context context;
private final List<Post> postsList;
class MyViewHolder extends RecyclerView.ViewHolder {
CardView cardView;
FrameLayout postDateAndNumberExp;
TextView postDate, postNum, username, subject;
CircularNetworkImageView thumbnail;
public WebView post;
ImageButton quoteToggle;
RelativeLayout header;
LinearLayout userExtraInfo;
TextView specialRank, rank, gender, numberOfPosts, personalText;
LinearLayout stars_holder;
final CardView cardView;
final FrameLayout postDateAndNumberExp;
final TextView postDate, postNum, username, subject;
final ImageView thumbnail;
final public WebView post;
final ImageButton quoteToggle;
final RelativeLayout header;
final LinearLayout userExtraInfo;
final TextView specialRank, rank, gender, numberOfPosts, personalText;
final LinearLayout stars_holder;
MyViewHolder(View view) {
super(view);
@ -68,7 +67,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
postDateAndNumberExp = (FrameLayout) view.findViewById(R.id.post_date_and_number_exp);
postDate = (TextView) view.findViewById(R.id.post_date);
postNum = (TextView) view.findViewById(R.id.post_number);
thumbnail = (CircularNetworkImageView) view.findViewById(R.id.thumbnail);
thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
username = (TextView) view.findViewById(R.id.username);
subject = (TextView) view.findViewById(R.id.subject);
post = (WebView) view.findViewById(R.id.post);
@ -83,14 +82,21 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
numberOfPosts = (TextView) view.findViewById(R.id.number_of_posts);
personalText = (TextView) view.findViewById(R.id.personal_text);
stars_holder = (LinearLayout) view.findViewById(R.id.stars);
}
/**
* Possible cleanup needed (like so:)
* https://stackoverflow.com/questions/24897441/picasso-how-to-cancel-all-image-requests-made-in-an-adapter
* TODO
*/
}
TopicAdapter(Context context, List<Post> postsList) {
this.context = context;
this.postsList = postsList;
THUMBNAIL_SIZE = (int) context.getResources().getDimension(R.dimen.thumbnail_size);
}
@Override
@ -109,7 +115,6 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder.post.setClickable(true);
holder.post.setWebViewClient(new LinkLauncher());
holder.post.getSettings().setJavaScriptEnabled(true);
holder.post.getSettings().setPluginState(WebSettings.PluginState.ON_DEMAND);
//Avoiding errors about layout having 0 width/height
holder.thumbnail.setMinimumWidth(1);
@ -118,11 +123,17 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE);
holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE);
//Thumbnail image set
if (currentPost.getThumbnailUrl() != null
&& !Objects.equals(currentPost.getThumbnailUrl(), "")) {
holder.thumbnail.setImageUrl(currentPost.getThumbnailUrl(), imageLoader);
}
//noinspection ConstantConditions
Picasso.with(context)
.load(currentPost.getThumbnailUrl())
.resize(THUMBNAIL_SIZE,THUMBNAIL_SIZE)
.centerCrop()
.error(ResourcesCompat.getDrawable(context.getResources()
, R.drawable.ic_default_user_thumbnail, null))
.placeholder(ResourcesCompat.getDrawable(context.getResources()
, R.drawable.ic_default_user_thumbnail, null))
.transform(new CircleTransform())
.into(holder.thumbnail);
//Username set
holder.username.setText(currentPost.getAuthor());
@ -163,12 +174,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
//If user is not deleted then we have more to do
if (!currentPost.isDeleted()) { //Set extra info
//Variables for content
String c_specialRank = currentPost.getSpecialRank()
, c_rank = currentPost.getRank()
, c_gender = currentPost.getGender()
, c_numberOfPosts = currentPost.getNumberOfPosts()
, c_personalText = currentPost.getPersonalText()
, c_urlOfStars = currentPost.getUrlOfStars();
String c_specialRank = currentPost.getSpecialRank(), c_rank = currentPost.getRank(), c_gender = currentPost.getGender(), c_numberOfPosts = currentPost.getNumberOfPosts(), c_personalText = currentPost.getPersonalText(), c_urlOfStars = currentPost.getUrlOfStars();
int c_numberOfStars = currentPost.getNumberOfStars();
if (!Objects.equals(c_specialRank, "") && c_specialRank != null) {
@ -193,11 +199,15 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
}
for (int i = 0; i < c_numberOfStars; ++i) {
CircularNetworkImageView star = new CircularNetworkImageView(context);
star.setImageUrl(c_urlOfStars, imageLoader);
ImageView star = new ImageView(context);
Picasso.with(context)
.load(c_urlOfStars)
.into(star);
//Remove spacing between stars...
//Don't know why this is happening in the first place
//TODO change layout? other solution?
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
@ -373,7 +383,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
private boolean handleUri(final Uri uri) {
//Method always returns true as we don't want any url to be loaded in WebViews
Log.i(TAG, "Uri = " + uri);
Log.i(TAG, "Uri clicked = " + uri);
final String host = uri.getHost(); //Get requested url's host
final String uriString = uri.toString();

5
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java

@ -26,6 +26,7 @@ class TopicParser {
private static String genderAltMale;
private static String genderAltFemale;
@SuppressWarnings("unused")
private static final String TAG = "TopicParser";
static int parseCurrentPageIndex(Document doc) {
@ -224,14 +225,14 @@ class TopicParser {
}
//Add new post in postsList, extended information needed
returnList.add(new Post(p_thumbnailUrl, p_userName, p_subject, p_post
, p_postIndex, p_postNum, p_postDate, false, p_rank
, p_postIndex, p_postNum, p_postDate, p_rank
, p_specialRank, p_gender, p_numberOfPosts, p_personalText
, p_urlOfStars, p_numberOfStars));
} else { //Deleted user
//Add new post in postsList, only standard information needed
returnList.add(new Post(p_thumbnailUrl, p_userName, p_subject
, p_post, p_postIndex, p_postNum, p_postDate, true));
, p_post, p_postIndex, p_postNum, p_postDate));
}
}
return returnList;

10
app/src/main/java/gr/thmmy/mthmmy/data/Post.java

@ -21,8 +21,8 @@ public class Post {
private int numberOfStars;
public Post(String thumbnailUrl, String author, String subject, String content
, int postIndex, int postNumber, String postDate, boolean isDeleted
, String rank, String special_rank, String gender, String numberOfPosts
, int postIndex, int postNumber, String postDate, String rank
, String special_rank, String gender, String numberOfPosts
, String personalText, String urlOfStars, int numberOfStars) {
this.thumbnailUrl = thumbnailUrl;
this.author = author;
@ -31,7 +31,7 @@ public class Post {
this.postIndex = postIndex;
this.postNumber = postNumber;
this.postDate = postDate;
this.isDeleted = isDeleted;
this.isDeleted = false;
this.rank = rank;
this.specialRank = special_rank;
this.gender = gender;
@ -42,7 +42,7 @@ public class Post {
}
public Post(String thumbnailUrl, String author, String subject, String content
, int postIndex, int postNumber, String postDate, boolean isDeleted) {
, int postIndex, int postNumber, String postDate) {
this.thumbnailUrl = thumbnailUrl;
this.author = author;
this.subject = subject;
@ -50,7 +50,7 @@ public class Post {
this.postIndex = postIndex;
this.postNumber = postNumber;
this.postDate = postDate;
this.isDeleted = isDeleted;
this.isDeleted = true;
rank = "Rank";
specialRank = "Special rank";
gender = "Gender";

7
app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java

@ -5,8 +5,6 @@ import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.franmontiel.persistentcookiejar.PersistentCookieJar;
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;
@ -23,7 +21,6 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gr.thmmy.mthmmy.utils.ImageController;
import okhttp3.Cookie;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
@ -302,7 +299,7 @@ public class SessionManager
return null;
}
private File getUserAvatar(String image_url, final String package_name, final String image_name) {
/*private File getUserAvatar(String image_url, final String package_name, final String image_name) {
final File[] returnImage = {null};
ImageController.getInstance().getImageLoader().get(image_url, new ImageLoader.ImageListener() {
@ -336,7 +333,7 @@ public class SessionManager
}
});
return returnImage[0];
}
}*/
/** Create a File for saving an image or video */
private File getOutputMediaFile(String packageName, String imageName){

57
app/src/main/java/gr/thmmy/mthmmy/utils/CircleTransform.java

@ -0,0 +1,57 @@
package gr.thmmy.mthmmy.utils;
/*
* Copyright 2014 Julian Shen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.squareup.picasso.Transformation;
public class CircleTransform implements Transformation {
@Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
@Override
public String key() {
return "circle";
}
}

72
app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java

@ -1,72 +0,0 @@
package gr.thmmy.mthmmy.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import com.android.volley.toolbox.NetworkImageView;
public class CircularNetworkImageView extends NetworkImageView {
private static final int THUMBNAIL_SIZE = 80;
private Context mContext;
public CircularNetworkImageView(Context context) {
super(context);
mContext = context;
}
public CircularNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mContext = context;
}
public CircularNetworkImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
@Override
public void setImageBitmap(Bitmap bm) {
if (bm == null) return;
setImageDrawable(new BitmapDrawable(mContext.getResources(),
getCircularBitmap(bm)));
}
/**
* Creates a circular bitmap and uses whichever dimension is smaller to determine the width
* <br/>Also constrains the circle to the leftmost part of the image
*/
private Bitmap getCircularBitmap(Bitmap bitmap) {
bitmap = Bitmap.createScaledBitmap(bitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
int size = bitmap.getWidth();
if (bitmap.getWidth() > bitmap.getHeight())
size = bitmap.getHeight();
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, size, size);
final RectF rectF = new RectF(rect);
final float roundPx = size / 2;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}

66
app/src/main/java/gr/thmmy/mthmmy/utils/ImageController.java

@ -1,66 +0,0 @@
package gr.thmmy.mthmmy.utils;
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
public class ImageController extends Application {
private static final String TAG = ImageController.class.getSimpleName();
private static ImageController mInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
public static synchronized ImageController getInstance() {
return mInstance;
}
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
private RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue,
new LruBitmapCache());
}
return this.mImageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests() {
mRequestQueue.cancelAll(new RequestQueue.RequestFilter() {
@Override
public boolean apply(Request<?> request) {
return true;
}
});
}
}

41
app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java

@ -1,41 +0,0 @@
package gr.thmmy.mthmmy.utils;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.android.volley.toolbox.ImageLoader.ImageCache;
class LruBitmapCache extends LruCache<String, Bitmap> implements
ImageCache {
private static final int CACHE_SIZE_DIVIDER = 8;
LruBitmapCache() {
this(getDefaultLruCacheSize());
}
private LruBitmapCache(int sizeInKiloBytes) {
super(sizeInKiloBytes);
}
private static int getDefaultLruCacheSize() {
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / CACHE_SIZE_DIVIDER;
return cacheSize;
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
@Override
public Bitmap getBitmap(String url) {
return get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
}

10
app/src/main/res/layout/activity_topic_post_row.xml

@ -81,15 +81,16 @@
android:layout_centerVertical="true"
android:layout_marginEnd="16dp">
<gr.thmmy.mthmmy.utils.CircularNetworkImageView
<ImageView
android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:src="@drawable/ic_default_user_thumbnail"
android:contentDescription="@string/thumbnail"
android:maxHeight="@dimen/thumbnail_size"
android:maxWidth="@dimen/thumbnail_size"/>
android:maxWidth="@dimen/thumbnail_size"
android:src="@drawable/ic_default_user_thumbnail"/>
</FrameLayout>
<TextView
@ -122,7 +123,8 @@
android:layout_height="@dimen/quote_button"
android:layout_marginEnd="9dp"
android:layout_marginTop="9dp"
android:background="@drawable/ic_toggle_quote_bg"/>
android:background="@drawable/ic_toggle_quote_bg"
android:contentDescription="@string/quote"/>
</LinearLayout>
<LinearLayout

3
app/src/main/res/values/dimens.xml

@ -3,8 +3,7 @@
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="appbar_padding_top">8dp</dimen>
<dimen name="thumbnail_size">80dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="thumbnail_size">44dp</dimen>
<dimen name="stars_margin">-15dp</dimen>
<dimen name="quote_button">36dp</dimen>
</resources>

2
app/src/main/res/values/strings.xml

@ -17,6 +17,8 @@
<string name="username">Username should be here&#8230;</string>
<string name="subject">Subject should be here&#8230;</string>
<string name="post">Post should be here&#8230;</string>
<string name="thumbnail">Thumbnail should be here&#8230;</string>
<string name="quote">Quote button should be here&#8230;</string>
<string name="text_first">first</string>
<string name="text_previous">previous</string>
<string name="text_page">Page</string>

2
build.gradle

@ -6,7 +6,7 @@ buildscript {
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.android.tools.build:gradle:2.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

Loading…
Cancel
Save