From 4469c309f6c1b970cf3027f23fe7c6c09a929c86 Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Mon, 25 Jul 2016 01:11:48 +0300 Subject: [PATCH 01/10] Trying to understand what to do.... --- app/build.gradle | 6 +- app/src/main/java/ru/yandex/yamblz/App.java | 5 +- .../main/java/ru/yandex/yamblz/Constants.java | 8 + .../loader/FourImagesCollageStrategy.java | 39 +++++ .../ru/yandex/yamblz/loader/GenreLoader.java | 87 +++++++++++ .../yamblz/loader/StubCollageLoader.java | 36 ++++- .../ru/yandex/yamblz/model/ArtistInfo.java | 144 ++++++++++++++++++ .../java/ru/yandex/yamblz/model/Cover.java | 28 ++++ .../java/ru/yandex/yamblz/model/Genre.java | 38 +++++ .../yamblz/ui/adapters/GenreListAdapter.java | 70 +++++++++ .../yamblz/ui/fragments/ContentFragment.java | 44 +++++- app/src/main/res/layout/fragment_content.xml | 9 +- app/src/main/res/layout/view_genre.xml | 18 +++ 13 files changed, 520 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/Constants.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/GenreLoader.java create mode 100644 app/src/main/java/ru/yandex/yamblz/model/ArtistInfo.java create mode 100644 app/src/main/java/ru/yandex/yamblz/model/Cover.java create mode 100644 app/src/main/java/ru/yandex/yamblz/model/Genre.java create mode 100644 app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java create mode 100644 app/src/main/res/layout/view_genre.xml diff --git a/app/build.gradle b/app/build.gradle index 445372a..c556e7c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,7 +15,8 @@ android { applicationId 'ru.yandex.yamblz' minSdkVersion versions.minSdk targetSdkVersion versions.targetSdk - versionCode versions.code // Notice that you may want to use BUILD_NUMBER from CI in real project with own CI. + versionCode versions.code + // Notice that you may want to use BUILD_NUMBER from CI in real project with own CI. versionName versions.name // Make generated apks contain version name and code. @@ -121,6 +122,9 @@ dependencies { exclude module: 'recyclerview-v7' exclude module: 'support-v4' } + compile 'io.reactivex:rxjava:1.1.6' + compile 'com.squareup.okhttp3:okhttp:3.2.0' + compile 'com.google.code.gson:gson:2.6.2' } configurations.all { diff --git a/app/src/main/java/ru/yandex/yamblz/App.java b/app/src/main/java/ru/yandex/yamblz/App.java index e5f9972..4dca2d1 100644 --- a/app/src/main/java/ru/yandex/yamblz/App.java +++ b/app/src/main/java/ru/yandex/yamblz/App.java @@ -8,6 +8,7 @@ import ru.yandex.yamblz.developer_settings.DeveloperSettingsModel; import ru.yandex.yamblz.handler.CriticalSectionsManager; import ru.yandex.yamblz.loader.CollageLoaderManager; +import ru.yandex.yamblz.loader.StubCollageLoader; import timber.log.Timber; public class App extends Application { @@ -34,8 +35,8 @@ public void onCreate() { devMetricsProxy.apply(); } - CollageLoaderManager.init(null); // add implementation - CriticalSectionsManager.init(null); // add implementation + CollageLoaderManager.init(new StubCollageLoader()); // TODO: add implementation + CriticalSectionsManager.init(null); // TODO: add implementation } @NonNull diff --git a/app/src/main/java/ru/yandex/yamblz/Constants.java b/app/src/main/java/ru/yandex/yamblz/Constants.java new file mode 100644 index 0000000..c2ab2d2 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/Constants.java @@ -0,0 +1,8 @@ +package ru.yandex.yamblz; + +/** + * Created by Aleksandra on 24/07/16. + */ +public interface Constants { + String MOBILIZATION_URL = "http://download.cdn.yandex.net/mobilization-2016/artists.json"; +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java b/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java new file mode 100644 index 0000000..117b6f7 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java @@ -0,0 +1,39 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.util.Log; + +import java.util.List; + +/** + * Created by Aleksandra on 24/07/16. + */ +public class FourImagesCollageStrategy implements CollageStrategy { + public static final String DEBUG_TAG = FourImagesCollageStrategy.class.getName(); + + @Override + public Bitmap create(List bitmaps) { + Log.d(DEBUG_TAG, "in create collage"); + + Bitmap result; + + if (bitmaps.size() >= 4) { + result = Bitmap.createBitmap(600, 600, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(result); + canvas.drawBitmap(bitmaps.get(0), 0, 0, null); + canvas.drawBitmap(bitmaps.get(1), 0, 300, null); + canvas.drawBitmap(bitmaps.get(2), 300, 0, null); + canvas.drawBitmap(bitmaps.get(3), 300, 300, null); + canvas.save(); + } else { + result = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(result); + canvas.drawBitmap(bitmaps.get(0), 0, 0, null); + canvas.save(); + } + + return result; + } + +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/GenreLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/GenreLoader.java new file mode 100644 index 0000000..d7648df --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/GenreLoader.java @@ -0,0 +1,87 @@ +package ru.yandex.yamblz.loader; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; +import android.util.Log; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; +import ru.yandex.yamblz.Constants; +import ru.yandex.yamblz.model.ArtistInfo; +import ru.yandex.yamblz.model.Genre; + +/** + * Created by Aleksandra on 25/07/16. + */ +public class GenreLoader extends AsyncTaskLoader> { + public static final String DEBUG_TAG = GenreLoader.class.getName(); + + private OkHttpClient client = new OkHttpClient(); + private Gson gson = new Gson(); + private TypeToken> artists = new TypeToken>() { + }; + + public GenreLoader(Context context) { + super(context); + } + + @Override + public List loadInBackground() { + Request request = new Request.Builder() + .url(Constants.MOBILIZATION_URL) + .build(); + + Response response; + try { + response = client.newCall(request).execute(); + ResponseBody responseBody = response.body(); + + List artistInfoList = gson.fromJson(responseBody.charStream(), artists.getType()); + responseBody.close(); + + Map genres = new HashMap<>(); + for (ArtistInfo a : artistInfoList) { + for (String g : a.getGenres()) { + if (genres.containsKey(g)) { + genres.get(g).getUrls().add(a.getCover().getSmall()); + } else { + List list = new ArrayList<>(); + list.add(a.getCover().getSmall()); + genres.put(g, new Genre(list, g)); + } + } + } + List result = new ArrayList<>(genres.size()); + + for (Map.Entry entry : genres.entrySet()) { + result.add(entry.getValue()); + } + + for (Genre g : result) { + Log.d(DEBUG_TAG, "" + g.toString()); + } + + return result; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onStartLoading() { + super.onStartLoading(); + forceLoad(); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index 1dc051b..274df5e 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -1,11 +1,19 @@ package ru.yandex.yamblz.loader; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.support.v7.app.AppCompatActivity; import android.widget.ImageView; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.LinkedList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class StubCollageLoader implements CollageLoader { - @Override public void loadCollage(List urls, ImageView imageView) { @@ -19,7 +27,13 @@ public void loadCollage(List urls, ImageTarget imageTarget) { @Override public void loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy) { + Bitmap collage = getCollage(urls, collageStrategy); + ((AppCompatActivity) imageView.getContext()).runOnUiThread(() -> { + imageView.setImageBitmap(collage); + imageView.invalidate(); + imageView.requestLayout(); + }); } @Override @@ -28,4 +42,24 @@ public void loadCollage(List urls, ImageTarget imageTarget, } + protected Bitmap getCollage(List stringUrls, CollageStrategy strategy) { + List bitmaps = new LinkedList<>(); + for (String url : stringUrls) { + try { + bitmaps.add(loadBitmapFromUrl(url)); + } catch (IOException e) { + e.printStackTrace(); + } + } + return strategy.create(bitmaps); + } + + protected Bitmap loadBitmapFromUrl(String stringUrl) throws IOException { + URL url = new URL(stringUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.connect(); + InputStream inputStream = connection.getInputStream(); + return BitmapFactory.decodeStream(inputStream); + } } diff --git a/app/src/main/java/ru/yandex/yamblz/model/ArtistInfo.java b/app/src/main/java/ru/yandex/yamblz/model/ArtistInfo.java new file mode 100644 index 0000000..9901c52 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/model/ArtistInfo.java @@ -0,0 +1,144 @@ +package ru.yandex.yamblz.model; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +/** + * Model + * + * @author Aleksandra Bobrova + */ +public class ArtistInfo implements Parcelable { + public static final Creator CREATOR = new Creator() { + @Override + public ArtistInfo createFromParcel(Parcel in) { + return new ArtistInfo(in); + } + + @Override + public ArtistInfo[] newArray(int size) { + return new ArtistInfo[size]; + } + }; + private long id; + private String name; + private List genres; + private long tracks; + private long albums; + private String link; + private String description; + private Cover cover; + + public ArtistInfo() { + } + + protected ArtistInfo(Parcel in) { + id = in.readLong(); + name = in.readString(); + genres = in.createStringArrayList(); + tracks = in.readLong(); + albums = in.readLong(); + link = in.readString(); + description = in.readString(); + cover = new Cover(); + cover.setBig(in.readString()); + cover.setSmall(in.readString()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(id); + dest.writeString(name); + dest.writeStringList(genres); + dest.writeLong(tracks); + dest.writeLong(albums); + dest.writeString(link); + dest.writeString(description); + dest.writeString(cover.getBig()); + dest.writeString(cover.getSmall()); + } + + @Override + public String toString() { + return "ArtistInfo{" + + "id=" + id + + ", name='" + name + '\'' + + ", genres=" + genres + + ", albums=" + albums + + ", link='" + link + '\'' + + ", description='" + description + '\'' + + ", cover=" + cover + + '}'; + } + + public long getId() { + return id; + } + + public String getLink() { + return link; + } + + public String getName() { + return name; + } + + public List getGenres() { + return genres; + } + + public Cover getCover() { + return cover; + } + + public long getAlbums() { + return albums; + } + + public String getDescription() { + return description; + } + + public long getTracks() { + return tracks; + } + + public void setId(long id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setGenres(List genres) { + this.genres = genres; + } + + public void setTracks(long tracks) { + this.tracks = tracks; + } + + public void setAlbums(long albums) { + this.albums = albums; + } + + public void setLink(String link) { + this.link = link; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setCover(Cover cover) { + this.cover = cover; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/model/Cover.java b/app/src/main/java/ru/yandex/yamblz/model/Cover.java new file mode 100644 index 0000000..3937838 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/model/Cover.java @@ -0,0 +1,28 @@ +package ru.yandex.yamblz.model; + +/** + * Created by Aleksandra on 20/07/16. + */ +public class Cover { + private String small; + private String big; + + public Cover() { + } + + public String getSmall() { + return small; + } + + public String getBig() { + return big; + } + + public void setSmall(String small) { + this.small = small; + } + + public void setBig(String big) { + this.big = big; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/model/Genre.java b/app/src/main/java/ru/yandex/yamblz/model/Genre.java new file mode 100644 index 0000000..838bd57 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/model/Genre.java @@ -0,0 +1,38 @@ +package ru.yandex.yamblz.model; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Aleksandra on 25/07/16. + */ +public class Genre { + private List urls; + private String name; + + public Genre(List urls, String name) { + this.urls = urls; + this.name = name; + } + + public List getUrls() { + return urls; + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return "Genre{" + + "urls=" + Arrays.deepToString(urls.toArray()) + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java new file mode 100644 index 0000000..3e2948b --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -0,0 +1,70 @@ +package ru.yandex.yamblz.ui.adapters; + +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.Arrays; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ru.yandex.yamblz.R; +import ru.yandex.yamblz.loader.CollageLoaderManager; +import ru.yandex.yamblz.loader.FourImagesCollageStrategy; +import ru.yandex.yamblz.model.Genre; + +/** + * Created by Aleksandra on 25/07/16. + */ +public class GenreListAdapter extends RecyclerView.Adapter { + public static final String DEBUG_TAG = GenreListAdapter.class.getName(); + private List dataset; + + @Override + public GenreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_genre, parent, false); + return new GenreViewHolder(v); + } + + @Override + public void onBindViewHolder(GenreViewHolder holder, int position) { + if (position < dataset.size()) { + Genre genre = dataset.get(position); + holder.name.setText(genre.getName()); + Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); + + new Thread(() -> { + CollageLoaderManager.getLoader().loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); + }).start(); + } + } + + @Override + public int getItemCount() { + return dataset != null ? dataset.size() : 0; + } + + public class GenreViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.text_view_genre) + TextView name; + + @BindView(R.id.image_view_genre) + ImageView image; + + public GenreViewHolder(View itemView) { + super(itemView); + + ButterKnife.bind(this, itemView); + } + } + + public void setDataset(List dataset) { + this.dataset = dataset; + notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java b/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java index d46490f..3744f73 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java @@ -3,16 +3,56 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; import ru.yandex.yamblz.R; +import ru.yandex.yamblz.loader.GenreLoader; +import ru.yandex.yamblz.model.Genre; +import ru.yandex.yamblz.ui.adapters.GenreListAdapter; + +public class ContentFragment extends BaseFragment implements LoaderManager.LoaderCallbacks> { + + @BindView(R.id.recycler_view) + RecyclerView recyclerView; + + private GenreListAdapter adapter; -public class ContentFragment extends BaseFragment { @NonNull @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_content, container, false); + View v = inflater.inflate(R.layout.fragment_content, container, false); + ButterKnife.bind(this, v); + + adapter = new GenreListAdapter(); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + + getLoaderManager().initLoader(1, null, this); + return v; + } + + @Override + public Loader> onCreateLoader(int id, Bundle args) { + return new GenreLoader(getActivity()); + } + + @Override + public void onLoadFinished(Loader> loader, List data) { + adapter.setDataset(data); + } + + @Override + public void onLoaderReset(Loader> loader) { + } } diff --git a/app/src/main/res/layout/fragment_content.xml b/app/src/main/res/layout/fragment_content.xml index 81016ea..92f7be0 100644 --- a/app/src/main/res/layout/fragment_content.xml +++ b/app/src/main/res/layout/fragment_content.xml @@ -3,12 +3,9 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + android:layout_height="match_parent"/> \ No newline at end of file diff --git a/app/src/main/res/layout/view_genre.xml b/app/src/main/res/layout/view_genre.xml new file mode 100644 index 0000000..a285f4d --- /dev/null +++ b/app/src/main/res/layout/view_genre.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file From 6765b785057f72138f47cb345bb5a5f4291426db Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Tue, 26 Jul 2016 16:18:02 +0300 Subject: [PATCH 02/10] Started 2nd task --- app/src/main/java/ru/yandex/yamblz/App.java | 7 ++- .../handler/CriticalSectionsManager.java | 5 +- .../handler/StubCriticalSectionsHandler.java | 52 +++++++++++++++++-- .../yandex/yamblz/loader/CollageLoader.java | 3 +- .../yamblz/loader/StubCollageLoader.java | 32 +++++++++--- .../ru/yandex/yamblz/ui/MyScrollListener.java | 29 +++++++++++ .../yamblz/ui/adapters/GenreListAdapter.java | 6 ++- .../yamblz/ui/fragments/ContentFragment.java | 2 + 8 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java diff --git a/app/src/main/java/ru/yandex/yamblz/App.java b/app/src/main/java/ru/yandex/yamblz/App.java index 4dca2d1..23c0d19 100644 --- a/app/src/main/java/ru/yandex/yamblz/App.java +++ b/app/src/main/java/ru/yandex/yamblz/App.java @@ -2,11 +2,14 @@ import android.app.Application; import android.content.Context; +import android.os.Handler; +import android.os.Looper; import android.support.annotation.NonNull; import ru.yandex.yamblz.developer_settings.DevMetricsProxy; import ru.yandex.yamblz.developer_settings.DeveloperSettingsModel; import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.handler.StubCriticalSectionsHandler; import ru.yandex.yamblz.loader.CollageLoaderManager; import ru.yandex.yamblz.loader.StubCollageLoader; import timber.log.Timber; @@ -35,8 +38,8 @@ public void onCreate() { devMetricsProxy.apply(); } - CollageLoaderManager.init(new StubCollageLoader()); // TODO: add implementation - CriticalSectionsManager.init(null); // TODO: add implementation + CollageLoaderManager.init(new StubCollageLoader()); + CriticalSectionsManager.init(new StubCriticalSectionsHandler(new Handler(Looper.getMainLooper()))); } @NonNull diff --git a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java index 8a3d496..f50ca5f 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java @@ -1,5 +1,8 @@ package ru.yandex.yamblz.handler; +import android.os.Handler; +import android.os.Looper; + public class CriticalSectionsManager { private static CriticalSectionsHandler sCriticalSectionsHandler; @@ -10,7 +13,7 @@ public static void init(CriticalSectionsHandler criticalSectionsHandler) { public static CriticalSectionsHandler getHandler() { if (sCriticalSectionsHandler == null) { - sCriticalSectionsHandler = new StubCriticalSectionsHandler(); + sCriticalSectionsHandler = new StubCriticalSectionsHandler(new Handler(Looper.getMainLooper())); } return sCriticalSectionsHandler; } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java index 0af9646..d9c7735 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java @@ -1,39 +1,81 @@ package ru.yandex.yamblz.handler; +import android.os.Handler; + +import java.util.LinkedList; +import java.util.List; + public class StubCriticalSectionsHandler implements CriticalSectionsHandler { + private final Handler handler; + private final List criticalSections = new LinkedList<>(); + private final List lowPriorityTasks = new LinkedList<>(); + private final LowPriorityTaskExecutor executor = new LowPriorityTaskExecutor(); + + public StubCriticalSectionsHandler(Handler handler) { + this.handler = handler; + } + @Override public void startSection(int id) { + criticalSections.add(id); + handler.removeCallbacks(executor); } @Override public void stopSection(int id) { - + criticalSections.remove(new Integer(0)); + if (criticalSections.isEmpty()) { + handler.post(executor); + } } @Override public void stopSections() { - + criticalSections.clear(); + handler.post(executor); } @Override public void postLowPriorityTask(Task task) { - + if (criticalSections.isEmpty() && lowPriorityTasks.isEmpty()) { + lowPriorityTasks.add(task); + handler.post(executor); + } else { + lowPriorityTasks.add(task); + } } @Override public void postLowPriorityTaskDelayed(Task task, int delay) { - + lowPriorityTasks.add(task); } @Override public void removeLowPriorityTask(Task task) { - + lowPriorityTasks.remove(task); } @Override public void removeLowPriorityTasks() { + handler.removeCallbacks(executor); + lowPriorityTasks.clear(); + } + public void executeLowPriorityTask() { + Task currentTask; + while (criticalSections.isEmpty() && !lowPriorityTasks.isEmpty()) { + currentTask = lowPriorityTasks.remove(0); + currentTask.run(); + } } + + public class LowPriorityTaskExecutor implements Runnable { + @Override + public void run() { + executeLowPriorityTask(); + } + } + } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java index dad5b76..4d3104b 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java @@ -2,6 +2,7 @@ import android.widget.ImageView; +import java.lang.ref.WeakReference; import java.util.List; public interface CollageLoader { @@ -10,7 +11,7 @@ public interface CollageLoader { void loadCollage(List urls, ImageTarget imageTarget); - void loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy); + void loadCollage(List urls, WeakReference imageView, CollageStrategy collageStrategy); void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy); diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index 274df5e..f896a36 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -2,16 +2,18 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.support.v7.app.AppCompatActivity; import android.widget.ImageView; import java.io.IOException; import java.io.InputStream; +import java.lang.ref.WeakReference; import java.net.HttpURLConnection; import java.net.URL; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; + +import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.handler.Task; public class StubCollageLoader implements CollageLoader { @Override @@ -25,15 +27,11 @@ public void loadCollage(List urls, ImageTarget imageTarget) { } @Override - public void loadCollage(List urls, ImageView imageView, + public void loadCollage(List urls, WeakReference imageView, CollageStrategy collageStrategy) { Bitmap collage = getCollage(urls, collageStrategy); - ((AppCompatActivity) imageView.getContext()).runOnUiThread(() -> { - imageView.setImageBitmap(collage); - imageView.invalidate(); - imageView.requestLayout(); - }); + CriticalSectionsManager.getHandler().postLowPriorityTask(new ImageSetter(imageView, collage)); } @Override @@ -62,4 +60,22 @@ protected Bitmap loadBitmapFromUrl(String stringUrl) throws IOException { InputStream inputStream = connection.getInputStream(); return BitmapFactory.decodeStream(inputStream); } + + public class ImageSetter implements Task { + + private WeakReference imageView; + private Bitmap collage; + + public ImageSetter(WeakReference imageView, Bitmap collage) { + this.imageView = imageView; + this.collage = collage; + } + + @Override + public void run() { + imageView.get().setImageBitmap(collage); + imageView.get().invalidate(); + imageView.get().requestLayout(); + } + } } diff --git a/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java b/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java new file mode 100644 index 0000000..9871893 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java @@ -0,0 +1,29 @@ +package ru.yandex.yamblz.ui; + +import android.support.v7.widget.RecyclerView; +import android.util.Log; + +import ru.yandex.yamblz.handler.CriticalSectionsManager; + +/** + * Created by Aleksandra on 26/07/16. + */ +public class MyScrollListener extends RecyclerView.OnScrollListener { + public static final String DEBUG_TAG = MyScrollListener.class.getName(); + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + + switch (newState) { + case RecyclerView.SCROLL_STATE_DRAGGING: + CriticalSectionsManager.getHandler().startSection(0); + Log.d(DEBUG_TAG, "In scroll state dragging"); + break; + case RecyclerView.SCROLL_STATE_IDLE: + Log.d(DEBUG_TAG, "In scroll state idle"); + CriticalSectionsManager.getHandler().stopSection(0); + break; + } + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java index 3e2948b..1375f31 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -8,6 +8,7 @@ import android.widget.ImageView; import android.widget.TextView; +import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.List; @@ -53,13 +54,14 @@ public class GenreViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.text_view_genre) TextView name; - @BindView(R.id.image_view_genre) - ImageView image; + WeakReference image; public GenreViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); + + image = new WeakReference((ImageView) itemView.findViewById(R.id.image_view_genre)); } } diff --git a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java b/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java index 3744f73..6bd1762 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java @@ -18,6 +18,7 @@ import ru.yandex.yamblz.R; import ru.yandex.yamblz.loader.GenreLoader; import ru.yandex.yamblz.model.Genre; +import ru.yandex.yamblz.ui.MyScrollListener; import ru.yandex.yamblz.ui.adapters.GenreListAdapter; public class ContentFragment extends BaseFragment implements LoaderManager.LoaderCallbacks> { @@ -36,6 +37,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c adapter = new GenreListAdapter(); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + recyclerView.addOnScrollListener(new MyScrollListener()); getLoaderManager().initLoader(1, null, this); return v; From a68e006edd452c912a7d484e950a6cb091e2039b Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Tue, 26 Jul 2016 21:23:17 +0300 Subject: [PATCH 03/10] Changed to Rx --- .../yamblz/loader/StubCollageLoader.java | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index f896a36..3eaf086 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -2,6 +2,8 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; import android.widget.ImageView; import java.io.IOException; @@ -12,10 +14,13 @@ import java.util.LinkedList; import java.util.List; -import ru.yandex.yamblz.handler.CriticalSectionsManager; -import ru.yandex.yamblz.handler.Task; +import rx.Observable; +import rx.Observer; +import rx.schedulers.Schedulers; public class StubCollageLoader implements CollageLoader { + public static final String DEBUG_TAG = StubCollageLoader.class.getName(); + @Override public void loadCollage(List urls, ImageView imageView) { @@ -29,9 +34,43 @@ public void loadCollage(List urls, ImageTarget imageTarget) { @Override public void loadCollage(List urls, WeakReference imageView, CollageStrategy collageStrategy) { - Bitmap collage = getCollage(urls, collageStrategy); + LinkedList bitmaps = new LinkedList<>(); + + Observable.from(urls).map(s -> { + try { + return loadBitmapFromUrl(s); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + }).collect( + () -> bitmaps, (bitmaps1, bitmap) -> bitmaps1.add(bitmap) + ).subscribeOn(Schedulers.io()).subscribe(new Observer>() { + @Override + public void onCompleted() { + Log.d(DEBUG_TAG, "Bitmap size + " + bitmaps.size()); + Bitmap collage = collageStrategy.create(bitmaps); + ((AppCompatActivity) imageView.get().getContext()).runOnUiThread(new Runnable() { + @Override + public void run() { + imageView.get().setImageBitmap(collage); + imageView.get().invalidate(); + } + }); + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onNext(LinkedList bitmaps) { + Log.d(DEBUG_TAG, "qq"); + } + }); + - CriticalSectionsManager.getHandler().postLowPriorityTask(new ImageSetter(imageView, collage)); } @Override @@ -40,18 +79,6 @@ public void loadCollage(List urls, ImageTarget imageTarget, } - protected Bitmap getCollage(List stringUrls, CollageStrategy strategy) { - List bitmaps = new LinkedList<>(); - for (String url : stringUrls) { - try { - bitmaps.add(loadBitmapFromUrl(url)); - } catch (IOException e) { - e.printStackTrace(); - } - } - return strategy.create(bitmaps); - } - protected Bitmap loadBitmapFromUrl(String stringUrl) throws IOException { URL url = new URL(stringUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); @@ -61,21 +88,4 @@ protected Bitmap loadBitmapFromUrl(String stringUrl) throws IOException { return BitmapFactory.decodeStream(inputStream); } - public class ImageSetter implements Task { - - private WeakReference imageView; - private Bitmap collage; - - public ImageSetter(WeakReference imageView, Bitmap collage) { - this.imageView = imageView; - this.collage = collage; - } - - @Override - public void run() { - imageView.get().setImageBitmap(collage); - imageView.get().invalidate(); - imageView.get().requestLayout(); - } - } } From c05f25d29edad24f64196dbfca2f152e3a4f11f7 Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Wed, 27 Jul 2016 00:02:28 +0300 Subject: [PATCH 04/10] Deleted threads --- .../yandex/yamblz/loader/CollageLoader.java | 4 +- .../yamblz/loader/StubCollageLoader.java | 63 +++++++++---------- .../yamblz/ui/adapters/GenreListAdapter.java | 23 +++++-- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java index 4d3104b..4e270b0 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java @@ -5,13 +5,15 @@ import java.lang.ref.WeakReference; import java.util.List; +import rx.Subscription; + public interface CollageLoader { void loadCollage(List urls, ImageView imageView); void loadCollage(List urls, ImageTarget imageTarget); - void loadCollage(List urls, WeakReference imageView, CollageStrategy collageStrategy); + Subscription loadCollage(List urls, WeakReference imageView, CollageStrategy collageStrategy); void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy); diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index 3eaf086..9a2320e 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -15,7 +15,8 @@ import java.util.List; import rx.Observable; -import rx.Observer; +import rx.Subscriber; +import rx.Subscription; import rx.schedulers.Schedulers; public class StubCollageLoader implements CollageLoader { @@ -32,45 +33,43 @@ public void loadCollage(List urls, ImageTarget imageTarget) { } @Override - public void loadCollage(List urls, WeakReference imageView, - CollageStrategy collageStrategy) { + public Subscription loadCollage(List urls, WeakReference imageView, + CollageStrategy collageStrategy) { LinkedList bitmaps = new LinkedList<>(); - Observable.from(urls).map(s -> { - try { - return loadBitmapFromUrl(s); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - }).collect( - () -> bitmaps, (bitmaps1, bitmap) -> bitmaps1.add(bitmap) - ).subscribeOn(Schedulers.io()).subscribe(new Observer>() { - @Override - public void onCompleted() { - Log.d(DEBUG_TAG, "Bitmap size + " + bitmaps.size()); - Bitmap collage = collageStrategy.create(bitmaps); - ((AppCompatActivity) imageView.get().getContext()).runOnUiThread(new Runnable() { + return Observable.from(urls) + .subscribeOn(Schedulers.newThread()) + .map(s -> { + try { + return loadBitmapFromUrl(s); + } catch (IOException e) { + Log.d(DEBUG_TAG, "error"); + e.printStackTrace(); + } + return null; + }).collect( + () -> bitmaps, LinkedList::add + ).subscribe(new Subscriber>() { @Override - public void run() { - imageView.get().setImageBitmap(collage); - imageView.get().invalidate(); + public void onCompleted() { + Log.d(DEBUG_TAG, "Bitmap size + " + bitmaps.size()); + Bitmap collage = collageStrategy.create(bitmaps); + ((AppCompatActivity) imageView.get().getContext()).runOnUiThread(() -> { + imageView.get().setImageBitmap(collage); + imageView.get().invalidate(); + }); } - }); - } - @Override - public void onError(Throwable e) { - - } + @Override + public void onError(Throwable e) { - @Override - public void onNext(LinkedList bitmaps) { - Log.d(DEBUG_TAG, "qq"); - } - }); + } + @Override + public void onNext(LinkedList bitmaps) { + } + }); } @Override diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java index 1375f31..01fad05 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -18,6 +18,7 @@ import ru.yandex.yamblz.loader.CollageLoaderManager; import ru.yandex.yamblz.loader.FourImagesCollageStrategy; import ru.yandex.yamblz.model.Genre; +import rx.Subscription; /** * Created by Aleksandra on 25/07/16. @@ -25,6 +26,7 @@ public class GenreListAdapter extends RecyclerView.Adapter { public static final String DEBUG_TAG = GenreListAdapter.class.getName(); private List dataset; + private Subscription subscription; @Override public GenreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @@ -39,12 +41,23 @@ public void onBindViewHolder(GenreViewHolder holder, int position) { holder.name.setText(genre.getName()); Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); - new Thread(() -> { - CollageLoaderManager.getLoader().loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); - }).start(); + subscription = CollageLoaderManager.getLoader().loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); } } + @Override + public void onViewRecycled(GenreViewHolder holder) { + super.onViewRecycled(holder); + subscription.unsubscribe(); + Log.d(DEBUG_TAG, "OnViewRecycled"); + } + + @Override + public void onViewAttachedToWindow(GenreViewHolder holder) { + super.onViewAttachedToWindow(holder); + Log.d(DEBUG_TAG, "onViewAttachedToWindow"); + } + @Override public int getItemCount() { return dataset != null ? dataset.size() : 0; @@ -61,7 +74,7 @@ public GenreViewHolder(View itemView) { ButterKnife.bind(this, itemView); - image = new WeakReference((ImageView) itemView.findViewById(R.id.image_view_genre)); + image = new WeakReference<>((ImageView) itemView.findViewById(R.id.image_view_genre)); } } @@ -69,4 +82,6 @@ public void setDataset(List dataset) { this.dataset = dataset; notifyDataSetChanged(); } + + } From 2cff2b8b535ca06cf5d325996b25b3a7b2404932 Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Wed, 27 Jul 2016 00:41:47 +0300 Subject: [PATCH 05/10] Moved subscription to VH --- .../yamblz/loader/StubCollageLoader.java | 35 +++++++++---------- .../yamblz/ui/adapters/GenreListAdapter.java | 27 +++++++++----- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index 9a2320e..fc603f2 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -38,18 +38,10 @@ public Subscription loadCollage(List urls, WeakReference imag LinkedList bitmaps = new LinkedList<>(); return Observable.from(urls) - .subscribeOn(Schedulers.newThread()) - .map(s -> { - try { - return loadBitmapFromUrl(s); - } catch (IOException e) { - Log.d(DEBUG_TAG, "error"); - e.printStackTrace(); - } - return null; - }).collect( - () -> bitmaps, LinkedList::add - ).subscribe(new Subscriber>() { + .observeOn(Schedulers.io()) + .map(this::loadBitmapFromUrl) + .collect(() -> bitmaps, LinkedList::add) + .subscribe(new Subscriber>() { @Override public void onCompleted() { Log.d(DEBUG_TAG, "Bitmap size + " + bitmaps.size()); @@ -78,13 +70,18 @@ public void loadCollage(List urls, ImageTarget imageTarget, } - protected Bitmap loadBitmapFromUrl(String stringUrl) throws IOException { - URL url = new URL(stringUrl); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setDoInput(true); - connection.connect(); - InputStream inputStream = connection.getInputStream(); - return BitmapFactory.decodeStream(inputStream); + protected Bitmap loadBitmapFromUrl(String stringUrl) { + try { + URL url = new URL(stringUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.connect(); + InputStream inputStream = connection.getInputStream(); + return BitmapFactory.decodeStream(inputStream); + } catch (IOException e) { + e.printStackTrace(); + } + return null; } } diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java index 01fad05..8c9d28e 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -26,7 +26,7 @@ public class GenreListAdapter extends RecyclerView.Adapter { public static final String DEBUG_TAG = GenreListAdapter.class.getName(); private List dataset; - private Subscription subscription; + @Override public GenreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @@ -41,14 +41,15 @@ public void onBindViewHolder(GenreViewHolder holder, int position) { holder.name.setText(genre.getName()); Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); - subscription = CollageLoaderManager.getLoader().loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); + Subscription subscription = CollageLoaderManager.getLoader().loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); + holder.setSubscription(subscription); } } @Override public void onViewRecycled(GenreViewHolder holder) { super.onViewRecycled(holder); - subscription.unsubscribe(); + holder.getSubscription().unsubscribe(); Log.d(DEBUG_TAG, "OnViewRecycled"); } @@ -58,12 +59,20 @@ public void onViewAttachedToWindow(GenreViewHolder holder) { Log.d(DEBUG_TAG, "onViewAttachedToWindow"); } + + public void setDataset(List dataset) { + this.dataset = dataset; + notifyDataSetChanged(); + } + @Override public int getItemCount() { return dataset != null ? dataset.size() : 0; } public class GenreViewHolder extends RecyclerView.ViewHolder { + private Subscription subscription; + @BindView(R.id.text_view_genre) TextView name; @@ -76,12 +85,14 @@ public GenreViewHolder(View itemView) { image = new WeakReference<>((ImageView) itemView.findViewById(R.id.image_view_genre)); } - } - public void setDataset(List dataset) { - this.dataset = dataset; - notifyDataSetChanged(); - } + public Subscription getSubscription() { + return subscription; + } + public void setSubscription(Subscription subscription) { + this.subscription = subscription; + } + } } From ea3f46a0d7f2068c0a962d7a667188c350ca3bd8 Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Wed, 27 Jul 2016 00:52:58 +0300 Subject: [PATCH 06/10] Minor improvements. --- .../yamblz/ui/adapters/GenreListAdapter.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java index 8c9d28e..1dd6dec 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -36,14 +36,17 @@ public GenreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @Override public void onBindViewHolder(GenreViewHolder holder, int position) { - if (position < dataset.size()) { - Genre genre = dataset.get(position); - holder.name.setText(genre.getName()); - Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); - - Subscription subscription = CollageLoaderManager.getLoader().loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); - holder.setSubscription(subscription); + if (holder.getSubscription() != null && holder.getSubscription().isUnsubscribed()) { + holder.getSubscription().unsubscribe(); } + Genre genre = dataset.get(position); + holder.name.setText(genre.getName()); + Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); + + Subscription subscription = CollageLoaderManager.getLoader() + .loadCollage(genre.getUrls(), new WeakReference<>(holder.image), new FourImagesCollageStrategy()); + holder.setSubscription(subscription); + } @Override @@ -76,14 +79,12 @@ public class GenreViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.text_view_genre) TextView name; - WeakReference image; + @BindView(R.id.image_view_genre) + ImageView image; public GenreViewHolder(View itemView) { super(itemView); - ButterKnife.bind(this, itemView); - - image = new WeakReference<>((ImageView) itemView.findViewById(R.id.image_view_genre)); } public Subscription getSubscription() { From 6c9d7fc078866ebf67126b65136e743cc5601a8c Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Wed, 27 Jul 2016 13:48:19 +0300 Subject: [PATCH 07/10] Rewrited loadCollage using advices. Added using critical section. Implemented loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy) --- app/build.gradle | 9 ++- .../main/java/ru/yandex/yamblz/Constants.java | 8 +- .../handler/CriticalSectionsManager.java | 5 +- .../handler/StubCriticalSectionsHandler.java | 2 +- .../yandex/yamblz/loader/CollageLoader.java | 9 +-- .../yamblz/loader/CollageLoaderManager.java | 5 +- .../yandex/yamblz/loader/CollageStrategy.java | 2 + .../loader/FourImagesCollageStrategy.java | 5 ++ .../yamblz/loader/ImageViewImageTarget.java | 26 +++++++ .../yamblz/loader/StubCollageLoader.java | 74 +++++++++++++------ .../ru/yandex/yamblz/ui/MyScrollListener.java | 2 + .../yamblz/ui/adapters/GenreListAdapter.java | 16 ++-- .../yamblz/ui/fragments/ContentFragment.java | 3 +- dependencies.gradle | 60 ++++++++------- 14 files changed, 151 insertions(+), 75 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java diff --git a/app/build.gradle b/app/build.gradle index c556e7c..a885b8d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,10 @@ dependencies { compile libraries.tinyDancer compile libraries.lynx compile libraries.processPhoenix + compile libraries.rxjava + compile libraries.rxandroid + compile libraries.okhttp + compile libraries.gson testCompile libraries.junit testCompile libraries.robolectric @@ -122,9 +126,8 @@ dependencies { exclude module: 'recyclerview-v7' exclude module: 'support-v4' } - compile 'io.reactivex:rxjava:1.1.6' - compile 'com.squareup.okhttp3:okhttp:3.2.0' - compile 'com.google.code.gson:gson:2.6.2' + + } configurations.all { diff --git a/app/src/main/java/ru/yandex/yamblz/Constants.java b/app/src/main/java/ru/yandex/yamblz/Constants.java index c2ab2d2..b486f7b 100644 --- a/app/src/main/java/ru/yandex/yamblz/Constants.java +++ b/app/src/main/java/ru/yandex/yamblz/Constants.java @@ -3,6 +3,10 @@ /** * Created by Aleksandra on 24/07/16. */ -public interface Constants { - String MOBILIZATION_URL = "http://download.cdn.yandex.net/mobilization-2016/artists.json"; +public final class Constants { + + public static final String MOBILIZATION_URL = "http://download.cdn.yandex.net/mobilization-2016/artists.json"; + + private Constants() { + } } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java index f50ca5f..3c4daaa 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java @@ -5,7 +5,10 @@ public class CriticalSectionsManager { - private static CriticalSectionsHandler sCriticalSectionsHandler; + private static volatile CriticalSectionsHandler sCriticalSectionsHandler; + + private CriticalSectionsManager() { + } public static void init(CriticalSectionsHandler criticalSectionsHandler) { sCriticalSectionsHandler = criticalSectionsHandler; diff --git a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java index d9c7735..67dc8c1 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java @@ -25,7 +25,7 @@ public void startSection(int id) { @Override public void stopSection(int id) { - criticalSections.remove(new Integer(0)); + criticalSections.remove(Integer.valueOf(0)); if (criticalSections.isEmpty()) { handler.post(executor); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java index 4e270b0..152d256 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java @@ -2,19 +2,18 @@ import android.widget.ImageView; -import java.lang.ref.WeakReference; import java.util.List; import rx.Subscription; public interface CollageLoader { - void loadCollage(List urls, ImageView imageView); + Subscription loadCollage(List urls, ImageView imageView); - void loadCollage(List urls, ImageTarget imageTarget); + Subscription loadCollage(List urls, ImageTarget imageTarget); - Subscription loadCollage(List urls, WeakReference imageView, CollageStrategy collageStrategy); + Subscription loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy); - void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy); + Subscription loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java index ef00d00..096f3a3 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java @@ -2,7 +2,10 @@ public class CollageLoaderManager { - private static CollageLoader sCollageLoader; + private static volatile CollageLoader sCollageLoader; + + private CollageLoaderManager() { + } public static void init(CollageLoader collageLoader) { sCollageLoader = collageLoader; diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java index d81d52d..3ae0317 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java @@ -6,5 +6,7 @@ public interface CollageStrategy { + int amountOfImagesNeeded(); + Bitmap create(List bitmaps); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java b/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java index 117b6f7..6262276 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/FourImagesCollageStrategy.java @@ -12,6 +12,11 @@ public class FourImagesCollageStrategy implements CollageStrategy { public static final String DEBUG_TAG = FourImagesCollageStrategy.class.getName(); + @Override + public int amountOfImagesNeeded() { + return 4; + } + @Override public Bitmap create(List bitmaps) { Log.d(DEBUG_TAG, "in create collage"); diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java new file mode 100644 index 0000000..bb51d6b --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java @@ -0,0 +1,26 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; +import android.widget.ImageView; + +import java.lang.ref.WeakReference; + +/** + * Created by Aleksandra on 27/07/16. + */ +public class ImageViewImageTarget implements ImageTarget { + private WeakReference reference; + + public ImageViewImageTarget(WeakReference reference) { + this.reference = reference; + } + + @Override + public void onLoadBitmap(Bitmap bitmap) { + final ImageView iv = reference.get(); + if (iv != null) { + iv.setImageBitmap(bitmap); + iv.invalidate(); + } + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index fc603f2..bef8b7d 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -2,8 +2,6 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.support.v7.app.AppCompatActivity; -import android.util.Log; import android.widget.ImageView; import java.io.IOException; @@ -13,43 +11,60 @@ import java.net.URL; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.Executors; +import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.handler.Task; import rx.Observable; +import rx.Scheduler; import rx.Subscriber; import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action2; import rx.schedulers.Schedulers; public class StubCollageLoader implements CollageLoader { public static final String DEBUG_TAG = StubCollageLoader.class.getName(); - @Override - public void loadCollage(List urls, ImageView imageView) { + private static final Scheduler SCHEDULER = Schedulers.from(Executors.newFixedThreadPool(10)); + @Override + public Subscription loadCollage(List urls, ImageView imageView) { + return loadCollage(urls, imageView, new FourImagesCollageStrategy()); } @Override - public void loadCollage(List urls, ImageTarget imageTarget) { + public Subscription loadCollage(List urls, ImageTarget imageTarget) { + return loadCollage(urls, imageTarget, new FourImagesCollageStrategy()); + } + @Override + public Subscription loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy) { + return loadCollage(urls, new ImageViewImageTarget(new WeakReference(imageView)), collageStrategy); } @Override - public Subscription loadCollage(List urls, WeakReference imageView, + public Subscription loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy) { - LinkedList bitmaps = new LinkedList<>(); + int n = Math.min(urls.size(), collageStrategy.amountOfImagesNeeded()); + urls = urls.subList(0, n); + return Observable.from(urls) - .observeOn(Schedulers.io()) - .map(this::loadBitmapFromUrl) - .collect(() -> bitmaps, LinkedList::add) - .subscribe(new Subscriber>() { + .flatMap(s -> Observable.just(s) + .observeOn(SCHEDULER) + .map(this::loadBitmapFromUrl)) + .collect(LinkedList::new, new Action2, Bitmap>() { + @Override + public void call(LinkedList bitmaps, Bitmap bitmap) { + bitmaps.add(bitmap); + } + }) + .map(collageStrategy::create) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Subscriber() { @Override public void onCompleted() { - Log.d(DEBUG_TAG, "Bitmap size + " + bitmaps.size()); - Bitmap collage = collageStrategy.create(bitmaps); - ((AppCompatActivity) imageView.get().getContext()).runOnUiThread(() -> { - imageView.get().setImageBitmap(collage); - imageView.get().invalidate(); - }); } @Override @@ -58,15 +73,11 @@ public void onError(Throwable e) { } @Override - public void onNext(LinkedList bitmaps) { - + public void onNext(Bitmap collage) { + CriticalSectionsManager.getHandler() + .postLowPriorityTask(new ImageViewSetter(imageTarget, collage)); } }); - } - - @Override - public void loadCollage(List urls, ImageTarget imageTarget, - CollageStrategy collageStrategy) { } @@ -84,4 +95,19 @@ protected Bitmap loadBitmapFromUrl(String stringUrl) { return null; } + public class ImageViewSetter implements Task { + private ImageTarget target; + private Bitmap collage; + + public ImageViewSetter(ImageTarget target, Bitmap collage) { + this.target = target; + this.collage = collage; + } + + @Override + public void run() { + target.onLoadBitmap(collage); + } + } + } diff --git a/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java b/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java index 9871893..bea3899 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java @@ -24,6 +24,8 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { Log.d(DEBUG_TAG, "In scroll state idle"); CriticalSectionsManager.getHandler().stopSection(0); break; + default: + break; } } } diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java index 1dd6dec..f303645 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -8,7 +8,7 @@ import android.widget.ImageView; import android.widget.TextView; -import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -25,7 +25,7 @@ */ public class GenreListAdapter extends RecyclerView.Adapter { public static final String DEBUG_TAG = GenreListAdapter.class.getName(); - private List dataset; + private List dataset = new ArrayList<>(); @Override @@ -36,30 +36,28 @@ public GenreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @Override public void onBindViewHolder(GenreViewHolder holder, int position) { - if (holder.getSubscription() != null && holder.getSubscription().isUnsubscribed()) { + if (holder.getSubscription() != null && !holder.getSubscription().isUnsubscribed()) { holder.getSubscription().unsubscribe(); } Genre genre = dataset.get(position); holder.name.setText(genre.getName()); Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); + holder.image.setImageDrawable(null); Subscription subscription = CollageLoaderManager.getLoader() - .loadCollage(genre.getUrls(), new WeakReference<>(holder.image), new FourImagesCollageStrategy()); + .loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); holder.setSubscription(subscription); - } @Override public void onViewRecycled(GenreViewHolder holder) { super.onViewRecycled(holder); holder.getSubscription().unsubscribe(); - Log.d(DEBUG_TAG, "OnViewRecycled"); } @Override public void onViewAttachedToWindow(GenreViewHolder holder) { super.onViewAttachedToWindow(holder); - Log.d(DEBUG_TAG, "onViewAttachedToWindow"); } @@ -74,13 +72,11 @@ public int getItemCount() { } public class GenreViewHolder extends RecyclerView.ViewHolder { - private Subscription subscription; - @BindView(R.id.text_view_genre) TextView name; - @BindView(R.id.image_view_genre) ImageView image; + private Subscription subscription; public GenreViewHolder(View itemView) { super(itemView); diff --git a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java b/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java index 6bd1762..712259f 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java @@ -26,7 +26,7 @@ public class ContentFragment extends BaseFragment implements LoaderManager.Loade @BindView(R.id.recycler_view) RecyclerView recyclerView; - private GenreListAdapter adapter; + private GenreListAdapter adapter = new GenreListAdapter(); @NonNull @Override @@ -34,7 +34,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c View v = inflater.inflate(R.layout.fragment_content, container, false); ButterKnife.bind(this, v); - adapter = new GenreListAdapter(); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.addOnScrollListener(new MyScrollListener()); diff --git a/dependencies.gradle b/dependencies.gradle index d9cb375..28aa8e9 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -23,6 +23,10 @@ ext.versions = [ supportLibs : '23.1.1', butterKnife : '8.0.1', timber : '4.1.2', + rxjava : '1.1.6', + rxandroid : '1.2.1', + okhttp : '3.2.0', + gson : '2.6.2', espresso : '2.2.1', stetho : '1.3.1', @@ -52,37 +56,41 @@ ext.gradlePlugins = [ ] ext.libraries = [ - dagger : "com.google.dagger:dagger:$versions.dagger", - daggerCompiler : "com.google.dagger:dagger-compiler:$versions.dagger", + dagger : "com.google.dagger:dagger:$versions.dagger", + daggerCompiler : "com.google.dagger:dagger-compiler:$versions.dagger", - autoValue : "com.google.auto.value:auto-value:$versions.autoValue", + autoValue : "com.google.auto.value:auto-value:$versions.autoValue", - supportAnnotations : "com.android.support:support-annotations:$versions.supportLibs", - supportAppCompat : "com.android.support:appcompat-v7:$versions.supportLibs", - supportDesign : "com.android.support:design:$versions.supportLibs", - supportRecyclerView : "com.android.support:recyclerview-v7:$versions.supportLibs", - supportCardView : "com.android.support:cardview-v7:$versions.supportLibs", + supportAnnotations : "com.android.support:support-annotations:$versions.supportLibs", + supportAppCompat : "com.android.support:appcompat-v7:$versions.supportLibs", + supportDesign : "com.android.support:design:$versions.supportLibs", + supportRecyclerView: "com.android.support:recyclerview-v7:$versions.supportLibs", + supportCardView : "com.android.support:cardview-v7:$versions.supportLibs", - butterKnife : "com.jakewharton:butterknife:$versions.butterKnife", - butterKnifeCompiler : "com.jakewharton:butterknife-compiler:$versions.butterKnife", - timber : "com.jakewharton.timber:timber:$versions.timber", + butterKnife : "com.jakewharton:butterknife:$versions.butterKnife", + butterKnifeCompiler: "com.jakewharton:butterknife-compiler:$versions.butterKnife", + timber : "com.jakewharton.timber:timber:$versions.timber", // Developer Tools - stetho : "com.facebook.stetho:stetho:$versions.stetho", - leakCanary : "com.squareup.leakcanary:leakcanary-android:$versions.leakCanary", - tinyDancer : "com.github.brianPlummer:tinydancer:$versions.tinyDancer", - lynx : "com.github.pedrovgs:lynx:$versions.lynx", - devMetricsNoOp : "com.frogermcs.androiddevmetrics:androiddevmetrics-runtime-noop:$versions.androidDevMetricsGradlePlugin", - processPhoenix : "com.jakewharton:process-phoenix:$versions.processPhoenix", + stetho : "com.facebook.stetho:stetho:$versions.stetho", + leakCanary : "com.squareup.leakcanary:leakcanary-android:$versions.leakCanary", + tinyDancer : "com.github.brianPlummer:tinydancer:$versions.tinyDancer", + lynx : "com.github.pedrovgs:lynx:$versions.lynx", + devMetricsNoOp : "com.frogermcs.androiddevmetrics:androiddevmetrics-runtime-noop:$versions.androidDevMetricsGradlePlugin", + processPhoenix : "com.jakewharton:process-phoenix:$versions.processPhoenix", + rxjava : "io.reactivex:rxjava:$versions.rxjava", + rxandroid : "io.reactivex:rxandroid:$versions.rxandroid", + okhttp : "com.squareup.okhttp3:okhttp:$versions.okhttp", + gson : "com.google.code.gson:gson:$versions.gson", // Test dependencies - junit : "junit:junit:$versions.junit", - robolectric : "org.robolectric:robolectric:$versions.robolectric", - assertJ : "org.assertj:assertj-core:$versions.assertJ", - equalsVerifier : "nl.jqno.equalsverifier:equalsverifier:$versions.equalsVerifier", - mockitoCore : "org.mockito:mockito-core:$versions.mockito", - supportTestRunner : "com.android.support.test:runner:$versions.supportTestRunner", - supportTestRules : "com.android.support.test:rules:$versions.supportTestRunner", - espressoCore : "com.android.support.test.espresso:espresso-core:$versions.espresso", - espressoContrib : "com.android.support.test.espresso:espresso-contrib:$versions.espresso", + junit : "junit:junit:$versions.junit", + robolectric : "org.robolectric:robolectric:$versions.robolectric", + assertJ : "org.assertj:assertj-core:$versions.assertJ", + equalsVerifier : "nl.jqno.equalsverifier:equalsverifier:$versions.equalsVerifier", + mockitoCore : "org.mockito:mockito-core:$versions.mockito", + supportTestRunner : "com.android.support.test:runner:$versions.supportTestRunner", + supportTestRules : "com.android.support.test:rules:$versions.supportTestRunner", + espressoCore : "com.android.support.test.espresso:espresso-core:$versions.espresso", + espressoContrib : "com.android.support.test.espresso:espresso-contrib:$versions.espresso", ] From 0151d5d24a75b4e033b55619f33398fc6d51886c Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Thu, 28 Jul 2016 12:16:33 +0300 Subject: [PATCH 08/10] Added closing connection to loadBitmapFromUrl() --- .../yamblz/loader/StubCollageLoader.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index bef8b7d..f6d72d8 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -82,17 +82,31 @@ public void onNext(Bitmap collage) { } protected Bitmap loadBitmapFromUrl(String stringUrl) { + Bitmap bitmap = null; + HttpURLConnection connection = null; + InputStream inputStream = null; try { URL url = new URL(stringUrl); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); - InputStream inputStream = connection.getInputStream(); - return BitmapFactory.decodeStream(inputStream); + inputStream = connection.getInputStream(); + bitmap = BitmapFactory.decodeStream(inputStream); } catch (IOException e) { e.printStackTrace(); + } finally { + if (connection != null) { + connection.disconnect(); + } + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } } - return null; + return bitmap; } public class ImageViewSetter implements Task { @@ -109,5 +123,4 @@ public void run() { target.onLoadBitmap(collage); } } - } From 1128205d5e22b46d67dd437ba1ed9e6e8c649178 Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Thu, 28 Jul 2016 12:32:09 +0300 Subject: [PATCH 09/10] Fixed bug with critical section. --- .../yamblz/handler/StubCriticalSectionsHandler.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java index 67dc8c1..a94ead2 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java @@ -18,14 +18,15 @@ public StubCriticalSectionsHandler(Handler handler) { @Override public void startSection(int id) { - criticalSections.add(id); - handler.removeCallbacks(executor); - + if (!criticalSections.contains(id)) { + criticalSections.add(id); + handler.removeCallbacks(executor); + } } @Override public void stopSection(int id) { - criticalSections.remove(Integer.valueOf(0)); + criticalSections.remove(Integer.valueOf(id)); if (criticalSections.isEmpty()) { handler.post(executor); } From 403d8e0a3563d45fe03528c99a6285a7c42d9a72 Mon Sep 17 00:00:00 2001 From: Aleksandra Bobrova Date: Thu, 28 Jul 2016 14:31:11 +0300 Subject: [PATCH 10/10] Fixed bug what replaced birmpas in imageView. --- .../handler/StubCriticalSectionsHandler.java | 22 ++++++------- .../yandex/yamblz/loader/CollageLoader.java | 10 +++--- .../ru/yandex/yamblz/loader/ImageTarget.java | 7 ++++ .../yamblz/loader/ImageViewImageTarget.java | 22 +++++++++++++ .../yamblz/loader/StubCollageLoader.java | 25 +++++++------- .../ru/yandex/yamblz/ui/MyScrollListener.java | 3 ++ .../yamblz/ui/adapters/GenreListAdapter.java | 33 +++++++++++-------- app/src/main/res/values/ids.xml | 5 +++ 8 files changed, 84 insertions(+), 43 deletions(-) create mode 100644 app/src/main/res/values/ids.xml diff --git a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java index a94ead2..4fb2884 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java @@ -2,14 +2,13 @@ import android.os.Handler; -import java.util.LinkedList; -import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class StubCriticalSectionsHandler implements CriticalSectionsHandler { private final Handler handler; - private final List criticalSections = new LinkedList<>(); - private final List lowPriorityTasks = new LinkedList<>(); + private final CopyOnWriteArrayList criticalSections = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList lowPriorityTasks = new CopyOnWriteArrayList<>(); private final LowPriorityTaskExecutor executor = new LowPriorityTaskExecutor(); public StubCriticalSectionsHandler(Handler handler) { @@ -64,19 +63,20 @@ public void removeLowPriorityTasks() { lowPriorityTasks.clear(); } - public void executeLowPriorityTask() { - Task currentTask; - while (criticalSections.isEmpty() && !lowPriorityTasks.isEmpty()) { - currentTask = lowPriorityTasks.remove(0); - currentTask.run(); - } - } public class LowPriorityTaskExecutor implements Runnable { @Override public void run() { executeLowPriorityTask(); } + + public void executeLowPriorityTask() { + Task currentTask; + while (criticalSections.isEmpty() && !lowPriorityTasks.isEmpty()) { + currentTask = lowPriorityTasks.remove(0); + currentTask.run(); + } + } } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java index 152d256..dad5b76 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java @@ -4,16 +4,14 @@ import java.util.List; -import rx.Subscription; - public interface CollageLoader { - Subscription loadCollage(List urls, ImageView imageView); + void loadCollage(List urls, ImageView imageView); - Subscription loadCollage(List urls, ImageTarget imageTarget); + void loadCollage(List urls, ImageTarget imageTarget); - Subscription loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy); + void loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy); - Subscription loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy); + void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy collageStrategy); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java index 9a8be2b..246e0ef 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java @@ -2,7 +2,14 @@ import android.graphics.Bitmap; +import ru.yandex.yamblz.handler.Task; +import rx.Subscription; + public interface ImageTarget { void onLoadBitmap(Bitmap bitmap); + + void setSubscription(Subscription subscription); + + void setTask(Task task); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java index bb51d6b..7174194 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageViewImageTarget.java @@ -1,10 +1,15 @@ package ru.yandex.yamblz.loader; import android.graphics.Bitmap; +import android.util.Log; import android.widget.ImageView; import java.lang.ref.WeakReference; +import ru.yandex.yamblz.R; +import ru.yandex.yamblz.handler.Task; +import rx.Subscription; + /** * Created by Aleksandra on 27/07/16. */ @@ -19,8 +24,25 @@ public ImageViewImageTarget(WeakReference reference) { public void onLoadBitmap(Bitmap bitmap) { final ImageView iv = reference.get(); if (iv != null) { + Log.d("qq", iv.getParent().toString()); iv.setImageBitmap(bitmap); iv.invalidate(); } } + + @Override + public void setSubscription(Subscription subscription) { + final ImageView iv = reference.get(); + if (iv != null) { + iv.setTag(R.id.tag_subscription, subscription); + } + } + + @Override + public void setTask(Task task) { + final ImageView iv = reference.get(); + if (iv != null) { + iv.setTag(R.id.tag_task, task); + } + } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java index f6d72d8..3bb97a2 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -29,28 +29,27 @@ public class StubCollageLoader implements CollageLoader { private static final Scheduler SCHEDULER = Schedulers.from(Executors.newFixedThreadPool(10)); @Override - public Subscription loadCollage(List urls, ImageView imageView) { - return loadCollage(urls, imageView, new FourImagesCollageStrategy()); + public void loadCollage(List urls, ImageView imageView) { + loadCollage(urls, imageView, new FourImagesCollageStrategy()); } @Override - public Subscription loadCollage(List urls, ImageTarget imageTarget) { - return loadCollage(urls, imageTarget, new FourImagesCollageStrategy()); + public void loadCollage(List urls, ImageTarget imageTarget) { + loadCollage(urls, imageTarget, new FourImagesCollageStrategy()); } @Override - public Subscription loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy) { - return loadCollage(urls, new ImageViewImageTarget(new WeakReference(imageView)), collageStrategy); + public void loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy) { + loadCollage(urls, new ImageViewImageTarget(new WeakReference(imageView)), collageStrategy); } @Override - public Subscription loadCollage(List urls, ImageTarget imageTarget, - CollageStrategy collageStrategy) { + public void loadCollage(List urls, ImageTarget imageTarget, + CollageStrategy collageStrategy) { int n = Math.min(urls.size(), collageStrategy.amountOfImagesNeeded()); urls = urls.subList(0, n); - - return Observable.from(urls) + Subscription subscription = Observable.from(urls) .flatMap(s -> Observable.just(s) .observeOn(SCHEDULER) .map(this::loadBitmapFromUrl)) @@ -74,11 +73,13 @@ public void onError(Throwable e) { @Override public void onNext(Bitmap collage) { + Task task = new ImageViewSetter(imageTarget, collage); + imageTarget.setTask(task); CriticalSectionsManager.getHandler() - .postLowPriorityTask(new ImageViewSetter(imageTarget, collage)); + .postLowPriorityTask(task); } }); - + imageTarget.setSubscription(subscription); } protected Bitmap loadBitmapFromUrl(String stringUrl) { diff --git a/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java b/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java index bea3899..dd45652 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/MyScrollListener.java @@ -20,6 +20,9 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { CriticalSectionsManager.getHandler().startSection(0); Log.d(DEBUG_TAG, "In scroll state dragging"); break; + case RecyclerView.SCROLL_STATE_SETTLING: + Log.d(DEBUG_TAG, "In scroll state settling"); + break; case RecyclerView.SCROLL_STATE_IDLE: Log.d(DEBUG_TAG, "In scroll state idle"); CriticalSectionsManager.getHandler().stopSection(0); diff --git a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java index f303645..9e21627 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/adapters/GenreListAdapter.java @@ -15,6 +15,8 @@ import butterknife.BindView; import butterknife.ButterKnife; import ru.yandex.yamblz.R; +import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.handler.Task; import ru.yandex.yamblz.loader.CollageLoaderManager; import ru.yandex.yamblz.loader.FourImagesCollageStrategy; import ru.yandex.yamblz.model.Genre; @@ -36,23 +38,35 @@ public GenreViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @Override public void onBindViewHolder(GenreViewHolder holder, int position) { - if (holder.getSubscription() != null && !holder.getSubscription().isUnsubscribed()) { - holder.getSubscription().unsubscribe(); + Log.d(DEBUG_TAG, "On bind" + holder.toString()); + + Subscription subscription = (Subscription) holder.image.getTag(R.id.tag_subscription); + if (subscription != null && !subscription.isUnsubscribed()) { + subscription.unsubscribe(); } + Genre genre = dataset.get(position); holder.name.setText(genre.getName()); Log.d(DEBUG_TAG, Arrays.deepToString(genre.getUrls().toArray())); holder.image.setImageDrawable(null); - Subscription subscription = CollageLoaderManager.getLoader() + holder.image.invalidate(); + CollageLoaderManager.getLoader() .loadCollage(genre.getUrls(), holder.image, new FourImagesCollageStrategy()); - holder.setSubscription(subscription); } @Override public void onViewRecycled(GenreViewHolder holder) { super.onViewRecycled(holder); - holder.getSubscription().unsubscribe(); + Subscription subscription = (Subscription) holder.image.getTag(R.id.tag_subscription); + if (subscription != null) { + subscription.unsubscribe(); + } + Task task = (Task) holder.image.getTag(R.id.tag_task); + if (task != null) { + CriticalSectionsManager.getHandler().removeLowPriorityTask(task); + } + Log.d(DEBUG_TAG, "Recycled" + holder.toString()); } @Override @@ -76,20 +90,11 @@ public class GenreViewHolder extends RecyclerView.ViewHolder { TextView name; @BindView(R.id.image_view_genre) ImageView image; - private Subscription subscription; public GenreViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } - - public Subscription getSubscription() { - return subscription; - } - - public void setSubscription(Subscription subscription) { - this.subscription = subscription; - } } } diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml new file mode 100644 index 0000000..e2d3cb3 --- /dev/null +++ b/app/src/main/res/values/ids.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file