From 8e38c2db1b9ecf1dcbd60a18c13f2002e2374e28 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Thu, 28 Jul 2016 03:39:18 +0300 Subject: [PATCH 01/13] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B2=D0=BE=D0=B5=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20(=D0=B1=D0=B5?= =?UTF-8?q?=D0=B7=20=D0=BA=D0=B5=D1=88=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B1=D0=B8=D1=82=D0=BC=D0=B0=D0=BF=D0=BE=D0=B2?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 5 + .../yandex/yamblz/genre/GenresFragment.java | 133 ++++++++++++++++++ .../yamblz/genre/GenresPresenterImpl.java | 70 +++++++++ .../yamblz/genre/adapter/CollageAdapter.java | 84 +++++++++++ .../yandex/yamblz/genre/api/ArtistsApi.java | 16 +++ .../yamblz/genre/data/entity/Artist.java | 63 +++++++++ .../yamblz/genre/data/entity/Cover.java | 24 ++++ .../yamblz/genre/data/entity/Genre.java | 32 +++++ .../yamblz/genre/data/source/Cache.java | 11 ++ .../yamblz/genre/data/source/CacheImpl.java | 69 +++++++++ .../yamblz/genre/data/source/DataSource.java | 15 ++ .../genre/data/source/RemoteDataSource.java | 36 +++++ .../yamblz/genre/data/source/Repository.java | 55 ++++++++ .../genre/interfaces/GenresPresenter.java | 11 ++ .../yamblz/genre/interfaces/GenresView.java | 14 ++ .../yandex/yamblz/genre/util/BitmapUtils.java | 42 ++++++ .../ru/yandex/yamblz/genre/util/Utils.java | 43 ++++++ .../yandex/yamblz/loader/CollageLoader.java | 1 - .../yamblz/loader/CollageLoaderManager.java | 14 +- .../yamblz/loader/CollageStrategyImpl.java | 49 +++++++ .../ru/yandex/yamblz/loader/Consumer.java | 34 +++++ .../yandex/yamblz/loader/ImageDownloader.java | 86 +++++++++++ .../ru/yandex/yamblz/loader/ImageTarget.java | 1 + .../yandex/yamblz/loader/ImageTargetImpl.java | 50 +++++++ .../yamblz/loader/SimpleCollageLoader.java | 73 ++++++++++ .../yamblz/loader/StubCollageLoader.java | 13 +- .../yamblz/ui/activities/MainActivity.java | 4 +- .../yamblz/ui/fragments/ContentFragment.java | 18 --- app/src/main/res/drawable/ic_place_holder.xml | 9 ++ app/src/main/res/layout/fragment_content.xml | 19 ++- dependencies.gradle | 6 + 31 files changed, 1060 insertions(+), 40 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/api/ArtistsApi.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresPresenter.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresView.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/util/BitmapUtils.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/Consumer.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java delete mode 100644 app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java create mode 100644 app/src/main/res/drawable/ic_place_holder.xml diff --git a/app/build.gradle b/app/build.gradle index 445372a..6220c53 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -96,6 +96,11 @@ dependencies { compile libraries.butterKnife apt libraries.butterKnifeCompiler + compile libraries.retrofit2 + compile libraries.rxAndroid + compile libraries.converterGson + compile libraries.adapterRxjava + compile libraries.timber // Developer tools (Developer Settings) diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java new file mode 100644 index 0000000..8ce2b2d --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java @@ -0,0 +1,133 @@ +package ru.yandex.yamblz.genre; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +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 android.widget.Toast; + +import java.io.File; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; +import ru.yandex.yamblz.R; +import ru.yandex.yamblz.genre.data.entity.Artist; +import ru.yandex.yamblz.genre.data.source.Cache; +import ru.yandex.yamblz.genre.data.source.CacheImpl; +import ru.yandex.yamblz.genre.data.source.DataSource; +import ru.yandex.yamblz.genre.data.source.RemoteDataSource; +import ru.yandex.yamblz.genre.data.source.Repository; +import ru.yandex.yamblz.loader.CollageLoader; +import ru.yandex.yamblz.loader.CollageLoaderManager; +import ru.yandex.yamblz.loader.SimpleCollageLoader; +import ru.yandex.yamblz.genre.adapter.CollageAdapter; +import ru.yandex.yamblz.genre.data.entity.Genre; +import ru.yandex.yamblz.genre.interfaces.GenresPresenter; +import ru.yandex.yamblz.genre.interfaces.GenresView; +import ru.yandex.yamblz.ui.fragments.BaseFragment; + +public class GenresFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener, GenresView { + + private static final String TAG = "GenresFragment"; + + private CollageLoader collageLoader; + private GenresPresenter presenter; + private CollageAdapter collageAdapter; + private Unbinder unbinder; + + @BindView(R.id.rv_collages) + RecyclerView recyclerView; + @BindView(R.id.swipe_view) + SwipeRefreshLayout swipeLayout; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + Handler responseHandler = new Handler(); + CollageLoaderManager.init(new SimpleCollageLoader(responseHandler)); + collageLoader = CollageLoaderManager.getLoader(); + + File cacheDir = getActivity().getCacheDir(); + Cache cache = new CacheImpl(cacheDir); + DataSource remoteDataSource = new RemoteDataSource(); + + presenter = new GenresPresenterImpl(Repository.getInstance(cache, remoteDataSource)); + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle bundle) + { + View view = inflater.inflate(R.layout.fragment_content, container, false); + unbinder = ButterKnife.bind(this, view); + return view; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + collageAdapter = new CollageAdapter(collageLoader); + recyclerView.setAdapter(collageAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + swipeLayout.setOnRefreshListener(this); + } + + @Override + public void onResume() + { + super.onResume(); + presenter.bind(this); + presenter.getGenres(false); + } + + @Override + public void onPause() + { + super.onPause(); + presenter.unsubscribe(); + presenter.unbind(); + } + + @Override + public void onDestroyView() + { + unbinder.unbind(); + super.onDestroyView(); + } + + @Override + public void showProgress(boolean show) + { + swipeLayout.setRefreshing(show); + } + + @Override + public void showGenres(List genresList) { + collageAdapter.swap(genresList); + } + + @Override + public void showError(String error) + { + Toast.makeText(getContext(), error, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onRefresh() + { + collageAdapter.clear(); + presenter.getGenres(true); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java new file mode 100644 index 0000000..ebba824 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java @@ -0,0 +1,70 @@ +package ru.yandex.yamblz.genre; + +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Genre; +import ru.yandex.yamblz.genre.data.source.DataSource; +import ru.yandex.yamblz.genre.interfaces.GenresPresenter; +import ru.yandex.yamblz.genre.interfaces.GenresView; +import ru.yandex.yamblz.genre.util.Utils; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + +/** + * Created by platon on 27.07.2016. + */ +public class GenresPresenterImpl implements GenresPresenter +{ + private GenresView genresView; + private CompositeSubscription subscriptions; + private DataSource dataSource; + + public GenresPresenterImpl(DataSource dataSource) + { + this.dataSource = dataSource; + subscriptions = new CompositeSubscription(); + } + + @Override + public void getGenres(boolean forceLoad) + { + genresView.showProgress(true); + if (forceLoad) dataSource.delete(); + + subscriptions.add(dataSource.getList() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .map(Utils::transformArtistToGenres) + .subscribe(onNext, onError)); + } + + @Override + public void bind(GenresView view) + { + genresView = view; + } + + @Override + public void unbind() + { + genresView = null; + } + + @Override + public void unsubscribe() + { + subscriptions.clear(); + } + + private Action1> onNext = genres -> { + genresView.showProgress(false); + genresView.showGenres(genres); + }; + + private Action1 onError = e -> { + genresView.showProgress(false); + genresView.showError(e.getMessage()); + }; +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java new file mode 100644 index 0000000..b11f0e4 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java @@ -0,0 +1,84 @@ +package ru.yandex.yamblz.genre.adapter; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ru.yandex.yamblz.R; +import ru.yandex.yamblz.loader.CollageLoader; +import ru.yandex.yamblz.loader.ImageTarget; +import ru.yandex.yamblz.loader.ImageTargetImpl; +import ru.yandex.yamblz.genre.data.entity.Genre; + +/** + * Created by platon on 26.07.2016. + */ +public class CollageAdapter extends RecyclerView.Adapter +{ + private CollageLoader collageLoader; + private List genres; + + public CollageAdapter(CollageLoader loader) + { + collageLoader = loader; + } + + @Override + public CollageItemHolder onCreateViewHolder(ViewGroup parent, int viewType) + { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_genre, parent, false); + return new CollageItemHolder(v); + } + + @Override + public void onBindViewHolder(CollageItemHolder holder, int position) + { + Genre genre = genres.get(position); + holder.bind(genre); + } + + @Override + public int getItemCount() + { + return genres == null ? 0 : genres.size(); + } + + public void swap(List newList) + { + genres = newList; + notifyDataSetChanged(); + } + + public void clear() + { + genres.clear(); + } + + public class CollageItemHolder extends RecyclerView.ViewHolder + { + @BindView(R.id.iv_collage_container) ImageView collageContainer; + @BindView(R.id.tw_genre) TextView genreTextView; + ImageTarget imageTarget = null; + + public CollageItemHolder(View view) + { + super(view); + ButterKnife.bind(this, view); + } + + public void bind(Genre genre) + { + collageContainer.setImageResource(R.drawable.ic_place_holder); + genreTextView.setText(genre.getName()); + imageTarget = new ImageTargetImpl(collageContainer); + collageLoader.loadCollage(genre.getUrls(), imageTarget); + } + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/api/ArtistsApi.java b/app/src/main/java/ru/yandex/yamblz/genre/api/ArtistsApi.java new file mode 100644 index 0000000..b38cc39 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/api/ArtistsApi.java @@ -0,0 +1,16 @@ +package ru.yandex.yamblz.genre.api; + +import java.util.List; + +import retrofit2.http.GET; +import ru.yandex.yamblz.genre.data.entity.Artist; +import rx.Observable; + +/** + * Created by platon on 27.07.2016. + */ +public interface ArtistsApi +{ + @GET("mobilization-2016/artists.json") + Observable> listArtists(); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java new file mode 100644 index 0000000..6918d6e --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java @@ -0,0 +1,63 @@ +package ru.yandex.yamblz.genre.data.entity; + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +/** + * Created by platon on 26.07.2016. + */ +public class Artist implements Serializable +{ + @SerializedName("id") + private String id; + + @SerializedName("name") + private String name; + + @SerializedName("genres") + private String[] genres; + + @SerializedName("cover") + private Cover cover; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String[] getGenres() + { + return genres; + } + + public void setGenres(String[] genres) + { + this.genres = genres; + } + + public Cover getCover() + { + return cover; + } + + public void setCover(Cover cover) + { + this.cover = cover; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java new file mode 100644 index 0000000..c4a2d57 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java @@ -0,0 +1,24 @@ +package ru.yandex.yamblz.genre.data.entity; + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +/** + * Created by platon on 26.07.2016. + */ +public class Cover implements Serializable +{ + @SerializedName("small") + private String coverUrl; + + public String getCoverUrl() + { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) + { + this.coverUrl = coverUrl; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java new file mode 100644 index 0000000..edeecbf --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java @@ -0,0 +1,32 @@ +package ru.yandex.yamblz.genre.data.entity; + +import java.util.List; + +/** + * Created by platon on 26.07.2016. + */ +public class Genre +{ + private List urls; + private String name; + + public List getUrls() + { + return urls; + } + + public void setUrls(List urls) + { + this.urls = urls; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java new file mode 100644 index 0000000..8725bbf --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java @@ -0,0 +1,11 @@ +package ru.yandex.yamblz.genre.data.source; + +import java.util.List; + +public interface Cache +{ + List get(); + void put(List list); + boolean clear(); + boolean isEmpty(); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java new file mode 100644 index 0000000..e1e6ac1 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java @@ -0,0 +1,69 @@ +package ru.yandex.yamblz.genre.data.source; + +import android.annotation.SuppressLint; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Artist; + +public class CacheImpl implements Cache +{ + private final File cachedFile; + + public CacheImpl(File cacheDir, String name) + { + cachedFile = new File(cacheDir, name); + } + + public CacheImpl(File cacheDir) + { + this(cacheDir, "artists.list"); + } + + @SuppressLint("NewApi") + @Override + public List get() + { + try (FileInputStream is = new FileInputStream(cachedFile); ObjectInputStream in = new ObjectInputStream(is)) + { + return (List) in.readObject(); + } + catch (ClassNotFoundException | IOException e) + { + e.printStackTrace(); + return null; + } + } + + @SuppressLint("NewApi") + @Override + public void put(List list) + { + try (FileOutputStream os = new FileOutputStream(cachedFile); ObjectOutputStream out = new ObjectOutputStream(os)) + { + out.writeObject(list); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + @Override + public boolean clear() + { + return cachedFile.delete(); + } + + @Override + public boolean isEmpty() + { + return !cachedFile.exists(); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java new file mode 100644 index 0000000..0010266 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java @@ -0,0 +1,15 @@ +package ru.yandex.yamblz.genre.data.source; + +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Artist; +import rx.Observable; + +/** + * Created by platon on 27.07.2016. + */ +public interface DataSource +{ + Observable> getList(); + void delete(); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java new file mode 100644 index 0000000..6d5c6d3 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java @@ -0,0 +1,36 @@ +package ru.yandex.yamblz.genre.data.source; + +import java.util.List; + +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; +import ru.yandex.yamblz.genre.api.ArtistsApi; +import ru.yandex.yamblz.genre.data.entity.Artist; +import rx.Observable; + +public class RemoteDataSource implements DataSource +{ + private static final String ENDPOINT = "http://download.cdn.yandex.net/"; + private ArtistsApi api; + + public RemoteDataSource() + { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(ENDPOINT) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .build(); + + api = retrofit.create(ArtistsApi.class); + } + + @Override + public Observable> getList() + { + return api.listArtists(); + } + + @Override + public void delete() {} +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java new file mode 100644 index 0000000..6780b2b --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java @@ -0,0 +1,55 @@ +package ru.yandex.yamblz.genre.data.source; + +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Artist; +import rx.Observable; + +/** + * Created by platon on 28.07.2016. + */ +public class Repository implements DataSource +{ + private static Repository sRepository; + + private Cache cache; + private DataSource remote; + + public static Repository getInstance(Cache cache, DataSource remote) + { + if (sRepository == null) + { + sRepository = new Repository(cache, remote); + } + return sRepository; + } + + private Repository(Cache cache, DataSource remote) + { + this.cache = cache; + this.remote = remote; + } + + @Override + public Observable> getList() + { + if (cache.isEmpty()) return fromRemote(); + return fromLocal(); + } + + @Override + public void delete() + { + cache.clear(); + } + + private Observable> fromRemote() + { + return remote.getList().doOnNext(artists -> cache.put(artists)); + } + + private Observable> fromLocal() + { + return Observable.just(cache.get()); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresPresenter.java b/app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresPresenter.java new file mode 100644 index 0000000..82bd826 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresPresenter.java @@ -0,0 +1,11 @@ +package ru.yandex.yamblz.genre.interfaces; + +/** + * Created by platon on 26.07.2016. + */ +public interface GenresPresenter { + void getGenres(boolean forceLoad); + void bind(T view); + void unbind(); + void unsubscribe(); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresView.java b/app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresView.java new file mode 100644 index 0000000..d5fad20 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/interfaces/GenresView.java @@ -0,0 +1,14 @@ +package ru.yandex.yamblz.genre.interfaces; + +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Genre; + +/** + * Created by platon on 26.07.2016. + */ +public interface GenresView { + void showProgress(boolean show); + void showGenres(List genres); + void showError(String error); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/util/BitmapUtils.java b/app/src/main/java/ru/yandex/yamblz/genre/util/BitmapUtils.java new file mode 100644 index 0000000..5a16f6c --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/util/BitmapUtils.java @@ -0,0 +1,42 @@ +package ru.yandex.yamblz.genre.util; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +/** + * Created by platon on 28.07.2016. + */ +public class BitmapUtils +{ + public static Bitmap decodeBitmapFromByte(byte[] bitmapBytes, int offset, int length, int reqWidth, + int reqHeight) { + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options); + + options.inSampleSize = calculateIiSampleSize(options, reqWidth, reqHeight); + options.inJustDecodeBounds = false; + + return BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options); + } + + public static int calculateIiSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) + { + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) + { + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) + { + inSampleSize *= 2; + } + } + + return inSampleSize; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java b/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java new file mode 100644 index 0000000..85ed4d8 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java @@ -0,0 +1,43 @@ +package ru.yandex.yamblz.genre.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Artist; +import ru.yandex.yamblz.genre.data.entity.Genre; + +/** + * Created by platon on 27.07.2016. + */ +public class Utils +{ + public static List transformArtistToGenres(List artists) + { + HashMap genresMap = new HashMap<>(); + List genresList = new ArrayList<>(); + + for (Artist a : artists) + { + for (String s : a.getGenres()) + { + if (genresMap.containsKey(s) && genresMap.get(s).getUrls().size() < 4) + { + genresMap.get(s).getUrls().add(a.getCover().getCoverUrl()); + } + else + { + List urls = new ArrayList<>(); + urls.add(a.getCover().getCoverUrl()); + Genre genre = new Genre(); + genre.setName(s); + genre.setUrls(urls); + genresMap.put(s, genre); + } + } + } + genresList.addAll(genresMap.values()); + + return genresList; + } +} 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..53ec68e 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java @@ -13,5 +13,4 @@ public interface CollageLoader { void loadCollage(List urls, ImageView imageView, CollageStrategy collageStrategy); void 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..e10ad0b 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java @@ -1,17 +1,21 @@ package ru.yandex.yamblz.loader; -public class CollageLoaderManager { - +public class CollageLoaderManager +{ private static CollageLoader sCollageLoader; - public static void init(CollageLoader collageLoader) { + public static void init(CollageLoader collageLoader) + { sCollageLoader = collageLoader; } - public static CollageLoader getLoader() { - if (sCollageLoader == null) { + public static CollageLoader getLoader() + { + if (sCollageLoader == null) + { sCollageLoader = new StubCollageLoader(); } + return sCollageLoader; } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java new file mode 100644 index 0000000..c33026d --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java @@ -0,0 +1,49 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; + +import java.util.List; + +/** + * Created by platon on 26.07.2016. + */ +public class CollageStrategyImpl implements CollageStrategy +{ + @Override + public Bitmap create(List bitmaps) + { + return combine(bitmaps); + } + + private Bitmap combine(List bitmaps) + { + if (bitmaps.size() != 4) return bitmaps.get(0); + + Paint paint = new Paint(); + paint.setColor(Color.WHITE); + + Bitmap first = bitmaps.get(0); + Bitmap second = bitmaps.get(1); + Bitmap third = bitmaps.get(2); + Bitmap fourth= bitmaps.get(3); + + int centerX = first.getWidth(); + int centerY = first.getHeight(); + + int width = centerX * 2; + int height = centerY * 2; + + Bitmap collage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + Canvas canvas = new Canvas(collage); + + canvas.drawBitmap(first, 0f, 0f, paint); + canvas.drawBitmap(second, centerX, 0f, paint); + canvas.drawBitmap(third, 0f, centerY, paint); + canvas.drawBitmap(fourth, centerX, centerY, paint); + + return collage; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/Consumer.java b/app/src/main/java/ru/yandex/yamblz/loader/Consumer.java new file mode 100644 index 0000000..abfafa1 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/Consumer.java @@ -0,0 +1,34 @@ +package ru.yandex.yamblz.loader; + +import java.util.concurrent.CountDownLatch; + +/** + * Created by platon on 27.07.2016. + */ +public class Consumer extends Thread { + + private final CountDownLatch countDownLatch; + private final Runnable result; + + public Consumer(Runnable result, CountDownLatch countDownLatch) + { + this.result = result; + this.countDownLatch = countDownLatch; + } + + @Override + public void run() { + super.run(); + + try + { + countDownLatch.await(); + result.run(); + + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java new file mode 100644 index 0000000..73a48a3 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java @@ -0,0 +1,86 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import ru.yandex.yamblz.genre.util.BitmapUtils; + +/** + * Created by platon on 27.07.2016. + */ +public class ImageDownloader implements Runnable +{ + private static final int READ_TIMEOUT = 10000; + private static final int CONNECTION_TIMEOUT = 15000; + private static final String REQUEST_METHOD = "GET"; + private static final int REQ_WIDTH = 100; + private static final int REQ_HEIGHT = 100; + + private final List bitmaps; + private final String url; + private final CountDownLatch countDownLatch; + + public ImageDownloader(String url, List bitmaps, CountDownLatch countDownLatch) + { + this.countDownLatch = countDownLatch; + this.bitmaps = bitmaps; + this.url = url; + } + + @Override + public void run() + { + HttpURLConnection conn = null; + + try + { + conn = getConnection(url); + byte[] bitmapBytes = getBytes(conn.getInputStream()); + bitmaps.add(BitmapUtils.decodeBitmapFromByte(bitmapBytes, 0, bitmapBytes.length, REQ_WIDTH, REQ_HEIGHT)); + + countDownLatch.countDown(); + } + catch (IOException e) + { + e.printStackTrace(); + } + finally + { + if (conn != null) { conn.disconnect(); } + } + } + + private byte[] getBytes(InputStream stream) throws IOException + { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + + while ((length = stream.read(buffer)) != -1) + { + result.write(buffer, 0, length); + } + + return result.toByteArray(); + } + + private HttpURLConnection getConnection(String urlString) throws IOException + { + URL url = new URL(urlString); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setReadTimeout(READ_TIMEOUT); + connection.setConnectTimeout(CONNECTION_TIMEOUT); + connection.setRequestMethod(REQUEST_METHOD); + connection.setDoInput(true); + + connection.connect(); + return connection; + } +} 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..cccc047 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java @@ -5,4 +5,5 @@ public interface ImageTarget { void onLoadBitmap(Bitmap bitmap); + void clear(); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java new file mode 100644 index 0000000..96c3a1c --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -0,0 +1,50 @@ +package ru.yandex.yamblz.loader; + +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.graphics.Bitmap; +import android.view.animation.AccelerateInterpolator; +import android.widget.ImageView; + +import java.lang.ref.WeakReference; + +/** + * Created by platon on 26.07.2016. + */ +public class ImageTargetImpl implements ImageTarget +{ + private static final long DURATION = 300; + private final WeakReference weakReference; + + public ImageTargetImpl(ImageView imageView) + { + weakReference = new WeakReference<>(imageView); + } + + @Override + public void onLoadBitmap(Bitmap bitmap) + { + ImageView imageView = weakReference.get(); + + if (imageView != null) + { + animateChange(imageView); + imageView.setImageBitmap(bitmap); + } + } + + @Override + public void clear() { + weakReference.clear(); + } + + private void animateChange(final ImageView imageView) + { + ObjectAnimator fadeIn = ObjectAnimator.ofFloat(imageView, "alpha", 0.0f, 1.0f); + fadeIn.setInterpolator(new AccelerateInterpolator()); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.setDuration(DURATION).play(fadeIn); + animatorSet.start(); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java new file mode 100644 index 0000000..1161f15 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java @@ -0,0 +1,73 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.widget.ImageView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class SimpleCollageLoader implements CollageLoader +{ + private static final int DEF_THREAD_COUNT = 4; + + private final CollageStrategy collageStrategy; + private Handler mainThreadHandler; + + public SimpleCollageLoader(Handler mainThreadHandler) + { + this.mainThreadHandler = mainThreadHandler; + collageStrategy = new CollageStrategyImpl(); + } + + @Override + public void loadCollage(List urls, ImageView imageView) + { + ImageTarget imageTarget = new ImageTargetImpl(imageView); + loadCollage(urls, imageTarget); + } + + @Override + public void loadCollage(List urls, ImageTarget imageTarget) + { + loadCollage(urls, imageTarget, collageStrategy); + } + + @Override + public void loadCollage(List urls, ImageView imageView, CollageStrategy strategy) + { + ImageTarget imageTarget = new ImageTargetImpl(imageView); + loadCollage(urls, imageTarget, strategy); + } + + @Override + public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) + { + int threadCount = urls.size() < DEF_THREAD_COUNT ? 1 : DEF_THREAD_COUNT; + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + CountDownLatch countDownLatch = new CountDownLatch(threadCount); + List bitmaps = Collections.synchronizedList(new ArrayList<>()); + + for(int i = 0; i < threadCount; i++) + { + executorService.submit(new ImageDownloader(urls.get(i), bitmaps, countDownLatch)); + } + + new Consumer(() -> postResult(bitmaps, imageTarget, strategy), countDownLatch).start(); + executorService.shutdown(); + } + + private void postResult(List bitmaps, ImageTarget imageTarget, CollageStrategy strategy) + { + mainThreadHandler.post(() -> { + Bitmap collage = strategy.create(bitmaps); + imageTarget.onLoadBitmap(collage); + }); + } +} 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..1b01892 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -7,25 +7,24 @@ public class StubCollageLoader implements CollageLoader { @Override - public void loadCollage(List urls, ImageView imageView) { + public void loadCollage(List urls, ImageView imageView) + { } @Override - public void loadCollage(List urls, ImageTarget imageTarget) { + public void loadCollage(List urls, ImageTarget imageTarget) + { } @Override - public void loadCollage(List urls, ImageView imageView, - CollageStrategy collageStrategy) { + public void loadCollage(List urls, ImageView imageView, CollageStrategy strategy) { } @Override - public void loadCollage(List urls, ImageTarget imageTarget, - CollageStrategy collageStrategy) { + public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) { } - } diff --git a/app/src/main/java/ru/yandex/yamblz/ui/activities/MainActivity.java b/app/src/main/java/ru/yandex/yamblz/ui/activities/MainActivity.java index 3b9efea..eb6b11c 100644 --- a/app/src/main/java/ru/yandex/yamblz/ui/activities/MainActivity.java +++ b/app/src/main/java/ru/yandex/yamblz/ui/activities/MainActivity.java @@ -9,8 +9,8 @@ import ru.yandex.yamblz.App; import ru.yandex.yamblz.R; +import ru.yandex.yamblz.genre.GenresFragment; import ru.yandex.yamblz.developer_settings.DeveloperSettingsModule; -import ru.yandex.yamblz.ui.fragments.ContentFragment; import ru.yandex.yamblz.ui.other.ViewModifier; public class MainActivity extends BaseActivity { @@ -29,7 +29,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { if (savedInstanceState == null) { getSupportFragmentManager() .beginTransaction() - .replace(R.id.main_frame_layout, new ContentFragment()) + .replace(R.id.main_frame_layout, new GenresFragment()) .commit(); } } 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 deleted file mode 100644 index d46490f..0000000 --- a/app/src/main/java/ru/yandex/yamblz/ui/fragments/ContentFragment.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.yandex.yamblz.ui.fragments; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import ru.yandex.yamblz.R; - -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); - } -} diff --git a/app/src/main/res/drawable/ic_place_holder.xml b/app/src/main/res/drawable/ic_place_holder.xml new file mode 100644 index 0000000..5cd87d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_place_holder.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_content.xml b/app/src/main/res/layout/fragment_content.xml index 81016ea..77ff0f6 100644 --- a/app/src/main/res/layout/fragment_content.xml +++ b/app/src/main/res/layout/fragment_content.xml @@ -3,12 +3,17 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + + + + \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle index d9cb375..9bd0211 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -23,6 +23,8 @@ ext.versions = [ supportLibs : '23.1.1', butterKnife : '8.0.1', timber : '4.1.2', + rxAndroid : '1.2.0', + retrofit2 : '2.0.1', espresso : '2.2.1', stetho : '1.3.1', @@ -66,6 +68,10 @@ ext.libraries = [ butterKnife : "com.jakewharton:butterknife:$versions.butterKnife", butterKnifeCompiler : "com.jakewharton:butterknife-compiler:$versions.butterKnife", timber : "com.jakewharton.timber:timber:$versions.timber", + rxAndroid : "io.reactivex:rxandroid:$versions.rxAndroid", + retrofit2 : "com.squareup.retrofit2:retrofit:$versions.retrofit2", + converterGson : "com.squareup.retrofit2:converter-gson:$versions.retrofit2", + adapterRxjava : "com.squareup.retrofit2:adapter-rxjava:$versions.retrofit2", // Developer Tools stetho : "com.facebook.stetho:stetho:$versions.stetho", From 9e79aeb4a1007e79da724d8c862899fc685a35a9 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Thu, 28 Jul 2016 04:09:06 +0300 Subject: [PATCH 02/13] update prev --- .../yamblz/genre/adapter/CollageAdapter.java | 3 +++ .../yandex/yamblz/loader/ImageTargetImpl.java | 3 ++- .../yamblz/loader/SimpleCollageLoader.java | 3 ++- .../yamblz/loader/StubCollageLoader.java | 22 +++++-------------- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java index b11f0e4..5a5307b 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java @@ -77,6 +77,9 @@ public void bind(Genre genre) { collageContainer.setImageResource(R.drawable.ic_place_holder); genreTextView.setText(genre.getName()); + + if (imageTarget != null) imageTarget.clear(); + imageTarget = new ImageTargetImpl(collageContainer); collageLoader.loadCollage(genre.getUrls(), imageTarget); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java index 96c3a1c..c543a92 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -34,7 +34,8 @@ public void onLoadBitmap(Bitmap bitmap) } @Override - public void clear() { + public void clear() + { weakReference.clear(); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java index 1161f15..bf8ac0a 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java @@ -18,6 +18,7 @@ public class SimpleCollageLoader implements CollageLoader private static final int DEF_THREAD_COUNT = 4; private final CollageStrategy collageStrategy; + private ImageTarget imageTarget; private Handler mainThreadHandler; public SimpleCollageLoader(Handler mainThreadHandler) @@ -29,7 +30,7 @@ public SimpleCollageLoader(Handler mainThreadHandler) @Override public void loadCollage(List urls, ImageView imageView) { - ImageTarget imageTarget = new ImageTargetImpl(imageView); + imageTarget = new ImageTargetImpl(imageView); loadCollage(urls, imageTarget); } 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 1b01892..54afe19 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -4,27 +4,17 @@ import java.util.List; -public class StubCollageLoader implements CollageLoader { - +public class StubCollageLoader implements CollageLoader +{ @Override - public void loadCollage(List urls, ImageView imageView) - { - - } + public void loadCollage(List urls, ImageView imageView) {} @Override - public void loadCollage(List urls, ImageTarget imageTarget) - { - - } + public void loadCollage(List urls, ImageTarget imageTarget) {} @Override - public void loadCollage(List urls, ImageView imageView, CollageStrategy strategy) { - - } + public void loadCollage(List urls, ImageView imageView, CollageStrategy strategy) {} @Override - public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) { - - } + public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) {} } From a8f5e3299b45678c1dc6f980289f4a0f5b194de1 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Thu, 28 Jul 2016 16:59:01 +0300 Subject: [PATCH 03/13] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=BA=D1=8D=D1=88=20=D0=B1=D0=B8=D1=82=D0=BC=D0=B0=D0=BF=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/ru/yandex/yamblz/App.java | 2 + .../yandex/yamblz/genre/GenresFragment.java | 3 +- .../yamblz/genre/adapter/CollageAdapter.java | 4 +- .../ru/yandex/yamblz/genre/util/Utils.java | 2 +- .../handler/CriticalSectionsHandler.java | 1 - .../ru/yandex/yamblz/loader/BitmapCache.java | 54 +++++++++++++++++++ .../yamblz/loader/CollageLoaderManager.java | 2 + .../yamblz/loader/CollageStrategyImpl.java | 2 + .../yandex/yamblz/loader/ImageDownloader.java | 33 ++++++++++-- .../yandex/yamblz/loader/ImageTargetImpl.java | 2 + .../yamblz/loader/SimpleCollageLoader.java | 12 ++--- .../yamblz/loader/StubCollageLoader.java | 4 ++ .../{ => interfaces}/CollageLoader.java | 2 +- .../{ => interfaces}/CollageStrategy.java | 2 +- .../yamblz/loader/interfaces/ImageCache.java | 12 +++++ .../loader/{ => interfaces}/ImageTarget.java | 2 +- 16 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java rename app/src/main/java/ru/yandex/yamblz/loader/{ => interfaces}/CollageLoader.java (90%) rename app/src/main/java/ru/yandex/yamblz/loader/{ => interfaces}/CollageStrategy.java (75%) create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageCache.java rename app/src/main/java/ru/yandex/yamblz/loader/{ => interfaces}/ImageTarget.java (73%) diff --git a/app/src/main/java/ru/yandex/yamblz/App.java b/app/src/main/java/ru/yandex/yamblz/App.java index e5f9972..f213ace 100644 --- a/app/src/main/java/ru/yandex/yamblz/App.java +++ b/app/src/main/java/ru/yandex/yamblz/App.java @@ -7,6 +7,7 @@ import ru.yandex.yamblz.developer_settings.DevMetricsProxy; import ru.yandex.yamblz.developer_settings.DeveloperSettingsModel; import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.loader.BitmapCache; import ru.yandex.yamblz.loader.CollageLoaderManager; import timber.log.Timber; @@ -34,6 +35,7 @@ public void onCreate() { devMetricsProxy.apply(); } + BitmapCache.init(); CollageLoaderManager.init(null); // add implementation CriticalSectionsManager.init(null); // add implementation } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java index 8ce2b2d..e0839e2 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java @@ -1,6 +1,5 @@ package ru.yandex.yamblz.genre; -import android.app.ProgressDialog; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; @@ -26,7 +25,7 @@ import ru.yandex.yamblz.genre.data.source.DataSource; import ru.yandex.yamblz.genre.data.source.RemoteDataSource; import ru.yandex.yamblz.genre.data.source.Repository; -import ru.yandex.yamblz.loader.CollageLoader; +import ru.yandex.yamblz.loader.interfaces.CollageLoader; import ru.yandex.yamblz.loader.CollageLoaderManager; import ru.yandex.yamblz.loader.SimpleCollageLoader; import ru.yandex.yamblz.genre.adapter.CollageAdapter; diff --git a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java index 5a5307b..05cd77e 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java @@ -12,8 +12,8 @@ import butterknife.BindView; import butterknife.ButterKnife; import ru.yandex.yamblz.R; -import ru.yandex.yamblz.loader.CollageLoader; -import ru.yandex.yamblz.loader.ImageTarget; +import ru.yandex.yamblz.loader.interfaces.CollageLoader; +import ru.yandex.yamblz.loader.interfaces.ImageTarget; import ru.yandex.yamblz.loader.ImageTargetImpl; import ru.yandex.yamblz.genre.data.entity.Genre; diff --git a/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java b/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java index 85ed4d8..18f1669 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/util/Utils.java @@ -21,7 +21,7 @@ public static List transformArtistToGenres(List artists) { for (String s : a.getGenres()) { - if (genresMap.containsKey(s) && genresMap.get(s).getUrls().size() < 4) + if (genresMap.containsKey(s)) { genresMap.get(s).getUrls().add(a.getCover().getCoverUrl()); } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java index 8b8cc56..ff110b4 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java @@ -15,5 +15,4 @@ public interface CriticalSectionsHandler { void removeLowPriorityTask(Task task); void removeLowPriorityTasks(); - } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java b/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java new file mode 100644 index 0000000..62cb140 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java @@ -0,0 +1,54 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; +import android.support.v4.util.LruCache; +import ru.yandex.yamblz.loader.interfaces.ImageCache; + +/** + * Created by platon on 28.07.2016. + */ +public class BitmapCache implements ImageCache +{ + private static BitmapCache sInstance; + private LruCache mMemoryCache; + + public static void init() + { + sInstance = new BitmapCache(); + } + + public static BitmapCache getCache() + { + return sInstance; + } + + private BitmapCache() + { + int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); + int cacheSize = maxMemory / 8; + + mMemoryCache = new LruCache(cacheSize) + { + @Override + protected int sizeOf(String key, Bitmap bitmap) + { + return bitmap.getByteCount() / 1024; + } + }; + } + + @Override + public void put(String key, Bitmap bitmap) + { + if (get(key) == null) + { + mMemoryCache.put(key, bitmap); + } + } + + @Override + public Bitmap get(String key) + { + return mMemoryCache.get(key); + } +} 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 e10ad0b..2743429 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java @@ -1,5 +1,7 @@ package ru.yandex.yamblz.loader; +import ru.yandex.yamblz.loader.interfaces.CollageLoader; + public class CollageLoaderManager { private static CollageLoader sCollageLoader; diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java index c33026d..86dc678 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java @@ -7,6 +7,8 @@ import java.util.List; +import ru.yandex.yamblz.loader.interfaces.CollageStrategy; + /** * Created by platon on 26.07.2016. */ diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java index 73a48a3..b9a4a78 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java @@ -1,6 +1,7 @@ package ru.yandex.yamblz.loader; import android.graphics.Bitmap; +import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -11,6 +12,7 @@ import java.util.concurrent.CountDownLatch; import ru.yandex.yamblz.genre.util.BitmapUtils; +import ru.yandex.yamblz.loader.interfaces.ImageCache; /** * Created by platon on 27.07.2016. @@ -26,10 +28,12 @@ public class ImageDownloader implements Runnable private final List bitmaps; private final String url; private final CountDownLatch countDownLatch; + private ImageCache bitmapCache; public ImageDownloader(String url, List bitmaps, CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; + bitmapCache = BitmapCache.getCache(); this.bitmaps = bitmaps; this.url = url; } @@ -37,15 +41,30 @@ public ImageDownloader(String url, List bitmaps, CountDownLatch countDow @Override public void run() { + if (bitmapCache.get(url) != null) + { + bitmaps.add(cachedBitmap()); + } + else + { + bitmaps.add(remoteBitmap()); + } + + countDownLatch.countDown(); + } + + private Bitmap remoteBitmap() + { + Log.d("Downloader", "fromRemote"); HttpURLConnection conn = null; + Bitmap bitmap = null; try { conn = getConnection(url); byte[] bitmapBytes = getBytes(conn.getInputStream()); - bitmaps.add(BitmapUtils.decodeBitmapFromByte(bitmapBytes, 0, bitmapBytes.length, REQ_WIDTH, REQ_HEIGHT)); - - countDownLatch.countDown(); + bitmap = BitmapUtils.decodeBitmapFromByte(bitmapBytes, 0, bitmapBytes.length, REQ_WIDTH, REQ_HEIGHT); + bitmapCache.put(url, bitmap); } catch (IOException e) { @@ -55,6 +74,14 @@ public void run() { if (conn != null) { conn.disconnect(); } } + + return bitmap; + } + + private Bitmap cachedBitmap() + { + Log.d("Downloader", "fromCache"); + return bitmapCache.get(url); } private byte[] getBytes(InputStream stream) throws IOException diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java index c543a92..d9777ac 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -8,6 +8,8 @@ import java.lang.ref.WeakReference; +import ru.yandex.yamblz.loader.interfaces.ImageTarget; + /** * Created by platon on 26.07.2016. */ diff --git a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java index bf8ac0a..a444e20 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java @@ -2,8 +2,6 @@ import android.graphics.Bitmap; import android.os.Handler; -import android.os.Looper; -import android.util.Log; import android.widget.ImageView; import java.util.ArrayList; @@ -13,12 +11,15 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import ru.yandex.yamblz.loader.interfaces.CollageLoader; +import ru.yandex.yamblz.loader.interfaces.CollageStrategy; +import ru.yandex.yamblz.loader.interfaces.ImageTarget; + public class SimpleCollageLoader implements CollageLoader { private static final int DEF_THREAD_COUNT = 4; private final CollageStrategy collageStrategy; - private ImageTarget imageTarget; private Handler mainThreadHandler; public SimpleCollageLoader(Handler mainThreadHandler) @@ -30,7 +31,7 @@ public SimpleCollageLoader(Handler mainThreadHandler) @Override public void loadCollage(List urls, ImageView imageView) { - imageTarget = new ImageTargetImpl(imageView); + ImageTarget imageTarget = new ImageTargetImpl(imageView); loadCollage(urls, imageTarget); } @@ -59,9 +60,8 @@ public void loadCollage(List urls, ImageTarget imageTarget, CollageStrat { executorService.submit(new ImageDownloader(urls.get(i), bitmaps, countDownLatch)); } - - new Consumer(() -> postResult(bitmaps, imageTarget, strategy), countDownLatch).start(); executorService.shutdown(); + new Consumer(() -> postResult(bitmaps, imageTarget, strategy), countDownLatch).start(); } private void postResult(List bitmaps, ImageTarget imageTarget, CollageStrategy strategy) 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 54afe19..67064b6 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java @@ -4,6 +4,10 @@ import java.util.List; +import ru.yandex.yamblz.loader.interfaces.CollageLoader; +import ru.yandex.yamblz.loader.interfaces.CollageStrategy; +import ru.yandex.yamblz.loader.interfaces.ImageTarget; + public class StubCollageLoader implements CollageLoader { @Override diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/CollageLoader.java similarity index 90% rename from app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java rename to app/src/main/java/ru/yandex/yamblz/loader/interfaces/CollageLoader.java index 53ec68e..f1c76d8 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/CollageLoader.java @@ -1,4 +1,4 @@ -package ru.yandex.yamblz.loader; +package ru.yandex.yamblz.loader.interfaces; import android.widget.ImageView; diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/CollageStrategy.java similarity index 75% rename from app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java rename to app/src/main/java/ru/yandex/yamblz/loader/interfaces/CollageStrategy.java index d81d52d..f4f30e6 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategy.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/CollageStrategy.java @@ -1,4 +1,4 @@ -package ru.yandex.yamblz.loader; +package ru.yandex.yamblz.loader.interfaces; import android.graphics.Bitmap; diff --git a/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageCache.java b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageCache.java new file mode 100644 index 0000000..fb754bb --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageCache.java @@ -0,0 +1,12 @@ +package ru.yandex.yamblz.loader.interfaces; + +import android.graphics.Bitmap; + +/** + * Created by platon on 28.07.2016. + */ +public interface ImageCache +{ + void put(String key, I image); + I get(String key); +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java similarity index 73% rename from app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java rename to app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java index cccc047..c94e511 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTarget.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java @@ -1,4 +1,4 @@ -package ru.yandex.yamblz.loader; +package ru.yandex.yamblz.loader.interfaces; import android.graphics.Bitmap; From 0a219fbe706fa0e7b235993e301a4c7cb93a998d Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Fri, 29 Jul 2016 03:22:00 +0300 Subject: [PATCH 04/13] =?UTF-8?q?=D0=93=D0=BE=D1=82=D0=BE=D0=B2=D0=BE=201?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/ru/yandex/yamblz/App.java | 27 ++++++---- .../yandex/yamblz/genre/GenresFragment.java | 16 ++---- .../yamblz/genre/GenresPresenterImpl.java | 23 ++++++--- .../yamblz/genre/adapter/CollageAdapter.java | 17 ++----- .../yamblz/genre/util/NetworkManager.java | 36 +++++++++++++ .../ru/yandex/yamblz/loader/BitmapCache.java | 10 ++-- .../yandex/yamblz/loader/CollageConsumer.java | 48 ++++++++++++++++++ .../yamblz/loader/CollageLoaderManager.java | 5 ++ .../ru/yandex/yamblz/loader/Consumer.java | 34 ------------- .../yandex/yamblz/loader/ImageDownloader.java | 3 -- .../yandex/yamblz/loader/ImageTargetImpl.java | 6 +++ .../yamblz/loader/SimpleCollageLoader.java | 50 +++++++++++++------ .../yamblz/loader/interfaces/ImageTarget.java | 2 + app/src/main/res/layout/fragment_content.xml | 11 ++-- app/src/main/res/layout/item_genre.xml | 28 +++++++++++ app/src/main/res/values/strings.xml | 2 +- gradle.properties | 2 +- 18 files changed, 216 insertions(+), 105 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/CollageConsumer.java delete mode 100644 app/src/main/java/ru/yandex/yamblz/loader/Consumer.java create mode 100644 app/src/main/res/layout/item_genre.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7baef8f..9ee0029 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="ru.yandex.yamblz"> + presenter; private CollageAdapter collageAdapter; private Unbinder unbinder; @@ -53,10 +48,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Handler responseHandler = new Handler(); - CollageLoaderManager.init(new SimpleCollageLoader(responseHandler)); - collageLoader = CollageLoaderManager.getLoader(); - File cacheDir = getActivity().getCacheDir(); Cache cache = new CacheImpl(cacheDir); DataSource remoteDataSource = new RemoteDataSource(); @@ -77,7 +68,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - collageAdapter = new CollageAdapter(collageLoader); + collageAdapter = new CollageAdapter(); recyclerView.setAdapter(collageAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); swipeLayout.setOnRefreshListener(this); @@ -126,7 +117,6 @@ public void showError(String error) @Override public void onRefresh() { - collageAdapter.clear(); presenter.getGenres(true); } } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java index ebba824..207ff6b 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java @@ -6,6 +6,7 @@ import ru.yandex.yamblz.genre.data.source.DataSource; import ru.yandex.yamblz.genre.interfaces.GenresPresenter; import ru.yandex.yamblz.genre.interfaces.GenresView; +import ru.yandex.yamblz.genre.util.NetworkManager; import ru.yandex.yamblz.genre.util.Utils; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; @@ -30,14 +31,22 @@ public GenresPresenterImpl(DataSource dataSource) @Override public void getGenres(boolean forceLoad) { - genresView.showProgress(true); - if (forceLoad) dataSource.delete(); + if (NetworkManager.getManager().networkIsAvailable()) + { + genresView.showProgress(true); + if (forceLoad) dataSource.delete(); - subscriptions.add(dataSource.getList() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .map(Utils::transformArtistToGenres) - .subscribe(onNext, onError)); + subscriptions.add(dataSource.getList() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .map(Utils::transformArtistToGenres) + .subscribe(onNext, onError)); + } + else + { + genresView.showProgress(false); + genresView.showError("no connection"); + } } @Override diff --git a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java index 05cd77e..dd926e5 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java @@ -12,6 +12,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import ru.yandex.yamblz.R; +import ru.yandex.yamblz.loader.CollageLoaderManager; import ru.yandex.yamblz.loader.interfaces.CollageLoader; import ru.yandex.yamblz.loader.interfaces.ImageTarget; import ru.yandex.yamblz.loader.ImageTargetImpl; @@ -25,9 +26,9 @@ public class CollageAdapter extends RecyclerView.Adapter genres; - public CollageAdapter(CollageLoader loader) + public CollageAdapter() { - collageLoader = loader; + collageLoader = CollageLoaderManager.getLoader(); } @Override @@ -56,16 +57,10 @@ public void swap(List newList) notifyDataSetChanged(); } - public void clear() - { - genres.clear(); - } - public class CollageItemHolder extends RecyclerView.ViewHolder { @BindView(R.id.iv_collage_container) ImageView collageContainer; @BindView(R.id.tw_genre) TextView genreTextView; - ImageTarget imageTarget = null; public CollageItemHolder(View view) { @@ -77,11 +72,7 @@ public void bind(Genre genre) { collageContainer.setImageResource(R.drawable.ic_place_holder); genreTextView.setText(genre.getName()); - - if (imageTarget != null) imageTarget.clear(); - - imageTarget = new ImageTargetImpl(collageContainer); - collageLoader.loadCollage(genre.getUrls(), imageTarget); + collageLoader.loadCollage(genre.getUrls(), collageContainer); } } } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java b/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java new file mode 100644 index 0000000..32cd92f --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java @@ -0,0 +1,36 @@ +package ru.yandex.yamblz.genre.util; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +/** + * Created by platon on 29.07.2016. + */ +public class NetworkManager +{ + private static NetworkManager sInstance; + private Context mContext; + + public static void init(Context context) + { + sInstance = new NetworkManager(context); + } + + public static NetworkManager getManager() + { + return sInstance; + } + + private NetworkManager(Context context) + { + mContext = context; + } + + public boolean networkIsAvailable() + { + ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeInfo = connMgr.getActiveNetworkInfo(); + return (activeInfo != null && activeInfo.isConnected()); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java b/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java index 62cb140..302e644 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/BitmapCache.java @@ -12,13 +12,13 @@ public class BitmapCache implements ImageCache private static BitmapCache sInstance; private LruCache mMemoryCache; - public static void init() - { - sInstance = new BitmapCache(); - } - public static BitmapCache getCache() { + if (sInstance == null) + { + sInstance = new BitmapCache(); + } + return sInstance; } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageConsumer.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageConsumer.java new file mode 100644 index 0000000..9d6f72f --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageConsumer.java @@ -0,0 +1,48 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; + +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import ru.yandex.yamblz.loader.interfaces.CollageStrategy; + +/** + * Created by platon on 29.07.2016. + */ +public class CollageConsumer extends Thread +{ + private Callback callback; + private CountDownLatch countDownLatch; + private CollageStrategy collageStrategy; + private List bitmaps; + + public interface Callback + { + void postCollage(Bitmap bitmap); + } + + public CollageConsumer(Callback callback, List bitmaps, CollageStrategy strategy, CountDownLatch cdl) + { + this.countDownLatch = cdl; + this.collageStrategy = strategy; + this.bitmaps = bitmaps; + this.callback = callback; + } + + @Override + public void run() + { + super.run(); + try + { + countDownLatch.await(); + Bitmap bitmap = collageStrategy.create(bitmaps); + callback.postCollage(bitmap); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} 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 2743429..268c3ee 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageLoaderManager.java @@ -20,4 +20,9 @@ public static CollageLoader getLoader() return sCollageLoader; } + + public static void destroy() + { + sCollageLoader = null; + } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/Consumer.java b/app/src/main/java/ru/yandex/yamblz/loader/Consumer.java deleted file mode 100644 index abfafa1..0000000 --- a/app/src/main/java/ru/yandex/yamblz/loader/Consumer.java +++ /dev/null @@ -1,34 +0,0 @@ -package ru.yandex.yamblz.loader; - -import java.util.concurrent.CountDownLatch; - -/** - * Created by platon on 27.07.2016. - */ -public class Consumer extends Thread { - - private final CountDownLatch countDownLatch; - private final Runnable result; - - public Consumer(Runnable result, CountDownLatch countDownLatch) - { - this.result = result; - this.countDownLatch = countDownLatch; - } - - @Override - public void run() { - super.run(); - - try - { - countDownLatch.await(); - result.run(); - - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java index b9a4a78..bcf4079 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java @@ -1,7 +1,6 @@ package ru.yandex.yamblz.loader; import android.graphics.Bitmap; -import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -55,7 +54,6 @@ public void run() private Bitmap remoteBitmap() { - Log.d("Downloader", "fromRemote"); HttpURLConnection conn = null; Bitmap bitmap = null; @@ -80,7 +78,6 @@ private Bitmap remoteBitmap() private Bitmap cachedBitmap() { - Log.d("Downloader", "fromCache"); return bitmapCache.get(url); } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java index d9777ac..90781f4 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -35,6 +35,12 @@ public void onLoadBitmap(Bitmap bitmap) } } + @Override + public ImageView getImageView() + { + return weakReference.get(); + } + @Override public void clear() { diff --git a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java index a444e20..ad17f89 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -20,12 +21,14 @@ public class SimpleCollageLoader implements CollageLoader private static final int DEF_THREAD_COUNT = 4; private final CollageStrategy collageStrategy; - private Handler mainThreadHandler; + private final Handler mainThreadHandler; + private final LinkedList imageTargets; - public SimpleCollageLoader(Handler mainThreadHandler) + public SimpleCollageLoader(Handler handler) { - this.mainThreadHandler = mainThreadHandler; + mainThreadHandler = handler; collageStrategy = new CollageStrategyImpl(); + imageTargets = new LinkedList<>(); } @Override @@ -51,24 +54,41 @@ public void loadCollage(List urls, ImageView imageView, CollageStrategy @Override public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) { - int threadCount = urls.size() < DEF_THREAD_COUNT ? 1 : DEF_THREAD_COUNT; - ExecutorService executorService = Executors.newFixedThreadPool(threadCount); - CountDownLatch countDownLatch = new CountDownLatch(threadCount); + int threadsCount = urls.size() < DEF_THREAD_COUNT ? 1 : DEF_THREAD_COUNT; + CountDownLatch cdl = new CountDownLatch(threadsCount); List bitmaps = Collections.synchronizedList(new ArrayList<>()); + ExecutorService downloadExecutor = Executors.newFixedThreadPool(threadsCount); - for(int i = 0; i < threadCount; i++) + clearDuplicate(imageTarget.getImageView()); + imageTargets.push(imageTarget); + + for(int i = 0; i < threadsCount; i++) { - executorService.submit(new ImageDownloader(urls.get(i), bitmaps, countDownLatch)); + ImageDownloader imgDownloader = new ImageDownloader(urls.get(i), bitmaps, cdl); + downloadExecutor.execute(imgDownloader); } - executorService.shutdown(); - new Consumer(() -> postResult(bitmaps, imageTarget, strategy), countDownLatch).start(); + + downloadExecutor.shutdown(); + + new CollageConsumer( + bitmap -> postResult(imageTarget, bitmap), + bitmaps, collageStrategy, cdl).start(); + } + + private void postResult(ImageTarget imageTarget, Bitmap bitmap) + { + mainThreadHandler.post(() -> imageTarget.onLoadBitmap(bitmap)); } - private void postResult(List bitmaps, ImageTarget imageTarget, CollageStrategy strategy) + private void clearDuplicate(ImageView newImgView) { - mainThreadHandler.post(() -> { - Bitmap collage = strategy.create(bitmaps); - imageTarget.onLoadBitmap(collage); - }); + if (newImgView != null) + { + for (ImageTarget it: imageTargets) + { + ImageView cachedImgView = it.getImageView(); + if (cachedImgView!= null && cachedImgView.equals(newImgView)) it.clear(); + } + } } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java index c94e511..3b8113c 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/interfaces/ImageTarget.java @@ -1,9 +1,11 @@ package ru.yandex.yamblz.loader.interfaces; import android.graphics.Bitmap; +import android.widget.ImageView; public interface ImageTarget { void onLoadBitmap(Bitmap bitmap); + ImageView getImageView(); void clear(); } diff --git a/app/src/main/res/layout/fragment_content.xml b/app/src/main/res/layout/fragment_content.xml index 77ff0f6..2f418ec 100644 --- a/app/src/main/res/layout/fragment_content.xml +++ b/app/src/main/res/layout/fragment_content.xml @@ -1,7 +1,8 @@ - + + android:layout_marginBottom="8dp" + android:scrollbars="vertical" + /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_genre.xml b/app/src/main/res/layout/item_genre.xml new file mode 100644 index 0000000..d3002b2 --- /dev/null +++ b/app/src/main/res/layout/item_genre.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7474f04..de8bd5d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - Yamblz + Genres Hello diff --git a/gradle.properties b/gradle.properties index 6b6a634..c1a64b5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ # Enlarge the gradle heap size. -org.gradle.jvmargs=-Xmx3584m -XX:MaxPermSize=1024m -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=1024m -Dfile.encoding=UTF-8 From 68df6f2eaeae1c68c53a4e66ba9d0c4e9a433007 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Fri, 29 Jul 2016 12:22:06 +0300 Subject: [PATCH 05/13] update --- .../java/ru/yandex/yamblz/genre/GenresPresenterImpl.java | 5 ++++- .../ru/yandex/yamblz/genre/util/INetworkManager.java | 9 +++++++++ .../java/ru/yandex/yamblz/genre/util/NetworkManager.java | 9 +++++---- 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/util/INetworkManager.java diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java index 207ff6b..3558cb4 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java @@ -6,6 +6,7 @@ import ru.yandex.yamblz.genre.data.source.DataSource; import ru.yandex.yamblz.genre.interfaces.GenresPresenter; import ru.yandex.yamblz.genre.interfaces.GenresView; +import ru.yandex.yamblz.genre.util.INetworkManager; import ru.yandex.yamblz.genre.util.NetworkManager; import ru.yandex.yamblz.genre.util.Utils; import rx.android.schedulers.AndroidSchedulers; @@ -21,17 +22,19 @@ public class GenresPresenterImpl implements GenresPresenter private GenresView genresView; private CompositeSubscription subscriptions; private DataSource dataSource; + private INetworkManager networkManager; public GenresPresenterImpl(DataSource dataSource) { this.dataSource = dataSource; + networkManager = NetworkManager.getManager(); subscriptions = new CompositeSubscription(); } @Override public void getGenres(boolean forceLoad) { - if (NetworkManager.getManager().networkIsAvailable()) + if (networkManager.networkIsAvailable()) { genresView.showProgress(true); if (forceLoad) dataSource.delete(); diff --git a/app/src/main/java/ru/yandex/yamblz/genre/util/INetworkManager.java b/app/src/main/java/ru/yandex/yamblz/genre/util/INetworkManager.java new file mode 100644 index 0000000..910a344 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/util/INetworkManager.java @@ -0,0 +1,9 @@ +package ru.yandex.yamblz.genre.util; + +/** + * Created by platon on 29.07.2016. + */ +public interface INetworkManager +{ + boolean networkIsAvailable(); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java b/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java index 32cd92f..f8bee82 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/util/NetworkManager.java @@ -7,10 +7,10 @@ /** * Created by platon on 29.07.2016. */ -public class NetworkManager +public class NetworkManager implements INetworkManager { private static NetworkManager sInstance; - private Context mContext; + private Context context; public static void init(Context context) { @@ -24,12 +24,13 @@ public static NetworkManager getManager() private NetworkManager(Context context) { - mContext = context; + this.context = context; } + @Override public boolean networkIsAvailable() { - ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeInfo = connMgr.getActiveNetworkInfo(); return (activeInfo != null && activeInfo.isConnected()); } From 6c6f0184e8feb9580c3f64ad613454e8408062f5 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Fri, 29 Jul 2016 16:59:33 +0300 Subject: [PATCH 06/13] update pojo --- .../yamblz/genre/data/entity/Artist.java | 42 +++++++++++++++++++ .../yamblz/genre/data/entity/Cover.java | 30 +++++++++++++ .../yamblz/genre/data/entity/Genre.java | 35 ++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java index 6918d6e..a55c265 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Artist.java @@ -3,6 +3,7 @@ import com.google.gson.annotations.SerializedName; import java.io.Serializable; +import java.util.Arrays; /** * Created by platon on 26.07.2016. @@ -60,4 +61,45 @@ public void setCover(Cover cover) { this.cover = cover; } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Artist artist = (Artist) o; + + if (!id.equals(artist.id)) return false; + if (!name.equals(artist.name)) return false; + return cover.equals(artist.cover); + + } + + @Override + public int hashCode() + { + int result = id.hashCode(); + result = 31 * result + name.hashCode(); + result = 31 * result + cover.hashCode(); + return result; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Artist{"); + builder.append("id="); + builder.append(id); + builder.append(", name="); + builder.append(name); + builder.append(", genres="); + builder.append(Arrays.toString(genres)); + builder.append(", cover="); + builder.append(cover); + builder.append("}"); + + return builder.toString(); + } } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java index c4a2d57..1645ead 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Cover.java @@ -21,4 +21,34 @@ public void setCoverUrl(String coverUrl) { this.coverUrl = coverUrl; } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Cover cover = (Cover) o; + + return coverUrl.equals(cover.coverUrl); + + } + + @Override + public int hashCode() + { + return coverUrl.hashCode(); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Cover{"); + builder.append("coverUrl="); + builder.append(coverUrl); + builder.append("}"); + + return builder.toString(); + } } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java index edeecbf..43b36a5 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/entity/Genre.java @@ -29,4 +29,39 @@ public void setName(String name) { this.name = name; } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Genre genre = (Genre) o; + + if (!urls.equals(genre.urls)) return false; + return name.equals(genre.name); + + } + + @Override + public int hashCode() + { + int result = urls.hashCode(); + result = 31 * result + name.hashCode(); + return result; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Genre{"); + builder.append("urls="); + builder.append(urls); + builder.append(", name="); + builder.append(name); + builder.append("}"); + + return builder.toString(); + } } From 6bd4c0bbf23d4a676da6acded8c4d22da639e347 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Fri, 29 Jul 2016 17:55:08 +0300 Subject: [PATCH 07/13] =?UTF-8?q?=D0=BF=D0=BE=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D0=B0=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5,=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B3=D0=B4=D0=B0=20=D0=B2=20=D1=81=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=BA=D0=B5=20=D0=B1=D0=B8=D1=82=D0=BC=D0=B0=D0=BF=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BB=D0=BB=D0=B0=D0=B6=D0=B0?= =?UTF-8?q?=20=D0=B8=D0=B7=204=D1=85=20=D0=B1=D1=8B=D0=BB=20=D1=85=D0=BE?= =?UTF-8?q?=D1=82=D1=8F=20=D0=B1=D1=8B=20=D0=BE=D0=B4=D0=B8=D0=BD=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yamblz/loader/CollageStrategyImpl.java | 48 ++++++++++++------- .../yandex/yamblz/loader/ImageTargetImpl.java | 2 +- .../yamblz/loader/SimpleCollageLoader.java | 2 +- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java index 86dc678..428d5e3 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CollageStrategyImpl.java @@ -1,6 +1,7 @@ package ru.yandex.yamblz.loader; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -22,30 +23,41 @@ public Bitmap create(List bitmaps) private Bitmap combine(List bitmaps) { - if (bitmaps.size() != 4) return bitmaps.get(0); - Paint paint = new Paint(); - paint.setColor(Color.WHITE); + if (bitmaps.size() == 4 && !containsNull(bitmaps)) + { + Paint paint = new Paint(); + paint.setColor(Color.WHITE); - Bitmap first = bitmaps.get(0); - Bitmap second = bitmaps.get(1); - Bitmap third = bitmaps.get(2); - Bitmap fourth= bitmaps.get(3); + Bitmap first = bitmaps.get(0); + Bitmap second = bitmaps.get(1); + Bitmap third = bitmaps.get(2); + Bitmap fourth = bitmaps.get(3); - int centerX = first.getWidth(); - int centerY = first.getHeight(); + int centerX = first.getWidth(); + int centerY = first.getHeight(); - int width = centerX * 2; - int height = centerY * 2; + int width = centerX * 2; + int height = centerY * 2; - Bitmap collage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); - Canvas canvas = new Canvas(collage); + Bitmap collage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + Canvas canvas = new Canvas(collage); - canvas.drawBitmap(first, 0f, 0f, paint); - canvas.drawBitmap(second, centerX, 0f, paint); - canvas.drawBitmap(third, 0f, centerY, paint); - canvas.drawBitmap(fourth, centerX, centerY, paint); + canvas.drawBitmap(first, 0f, 0f, paint); + canvas.drawBitmap(second, centerX, 0f, paint); + canvas.drawBitmap(third, 0f, centerY, paint); + canvas.drawBitmap(fourth, centerX, centerY, paint); - return collage; + return collage; + } + else + { + return bitmaps.get(0); + } + } + + private boolean containsNull(List bitmaps) + { + return (bitmaps.contains(null)); } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java index 90781f4..37393d6 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -28,7 +28,7 @@ public void onLoadBitmap(Bitmap bitmap) { ImageView imageView = weakReference.get(); - if (imageView != null) + if (imageView != null && bitmap != null) { animateChange(imageView); imageView.setImageBitmap(bitmap); diff --git a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java index ad17f89..e62105f 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/SimpleCollageLoader.java @@ -72,7 +72,7 @@ public void loadCollage(List urls, ImageTarget imageTarget, CollageStrat new CollageConsumer( bitmap -> postResult(imageTarget, bitmap), - bitmaps, collageStrategy, cdl).start(); + bitmaps, strategy, cdl).start(); } private void postResult(ImageTarget imageTarget, Bitmap bitmap) From 7c5e853e4aff3d3ccedf6941499ec5f08b331613 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Sun, 31 Jul 2016 03:25:17 +0300 Subject: [PATCH 08/13] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=BE=D0=B5=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/ru/yandex/yamblz/App.java | 12 +- .../yandex/yamblz/genre/GenresFragment.java | 1 + .../yamblz/genre/RecyclerScrollListener.java | 37 ++++++ .../yamblz/genre/adapter/CollageAdapter.java | 1 - .../handler/CriticalSectionsHandler.java | 4 +- .../handler/CriticalSectionsManager.java | 14 ++- .../handler/SimpleCriticalSectionHandler.java | 118 ++++++++++++++++++ .../handler/StubCriticalSectionsHandler.java | 32 ++--- .../java/ru/yandex/yamblz/handler/Task.java | 6 +- .../yamblz/handler/TaskSetImageView.java | 37 ++++++ .../loader/CriticalSectionsCollageLoader.java | 100 +++++++++++++++ .../yandex/yamblz/loader/ImageTargetImpl.java | 6 + app/src/main/res/layout/item_genre.xml | 1 + 13 files changed, 332 insertions(+), 37 deletions(-) create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/RecyclerScrollListener.java create mode 100644 app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java create mode 100644 app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java create mode 100644 app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java diff --git a/app/src/main/java/ru/yandex/yamblz/App.java b/app/src/main/java/ru/yandex/yamblz/App.java index 0cdba38..c13a0a6 100644 --- a/app/src/main/java/ru/yandex/yamblz/App.java +++ b/app/src/main/java/ru/yandex/yamblz/App.java @@ -9,8 +9,9 @@ import ru.yandex.yamblz.developer_settings.DeveloperSettingsModel; import ru.yandex.yamblz.genre.util.NetworkManager; import ru.yandex.yamblz.handler.CriticalSectionsManager; -import ru.yandex.yamblz.loader.BitmapCache; +import ru.yandex.yamblz.handler.SimpleCriticalSectionHandler; import ru.yandex.yamblz.loader.CollageLoaderManager; +import ru.yandex.yamblz.loader.CriticalSectionsCollageLoader; import ru.yandex.yamblz.loader.SimpleCollageLoader; import timber.log.Timber; @@ -43,8 +44,13 @@ public void onCreate() } NetworkManager.init(getApplicationContext()); - CollageLoaderManager.init(new SimpleCollageLoader(new Handler(getMainLooper()))); - CriticalSectionsManager.init(null); + + // первое задание, раскомментировать + //CollageLoaderManager.init(new SimpleCollageLoader(new Handler(getMainLooper()))); + + //второе задание, соотвественно, закомментировать + CriticalSectionsManager.init(new SimpleCriticalSectionHandler(new Handler(getMainLooper()))); + CollageLoaderManager.init(new CriticalSectionsCollageLoader()); } @NonNull diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java index b63b140..ab518f4 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java @@ -72,6 +72,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) recyclerView.setAdapter(collageAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); swipeLayout.setOnRefreshListener(this); + recyclerView.addOnScrollListener(new RecyclerScrollListener()); } @Override diff --git a/app/src/main/java/ru/yandex/yamblz/genre/RecyclerScrollListener.java b/app/src/main/java/ru/yandex/yamblz/genre/RecyclerScrollListener.java new file mode 100644 index 0000000..c4352ba --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/RecyclerScrollListener.java @@ -0,0 +1,37 @@ +package ru.yandex.yamblz.genre; + +import android.support.v7.widget.RecyclerView; + +import ru.yandex.yamblz.handler.CriticalSectionsHandler; +import ru.yandex.yamblz.handler.CriticalSectionsManager; + +/** + * Created by platon on 30.07.2016. + */ +public class RecyclerScrollListener extends RecyclerView.OnScrollListener +{ + public static final int CS_ID = 1991; + private final CriticalSectionsHandler criticalSectionsHandler; + + public RecyclerScrollListener() + { + super(); + criticalSectionsHandler = CriticalSectionsManager.getHandler(); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) + { + switch (newState) + { + case RecyclerView.SCROLL_STATE_IDLE: + criticalSectionsHandler.stopSection(CS_ID); + break; + + case RecyclerView.SCROLL_STATE_DRAGGING: + criticalSectionsHandler.startSection(CS_ID); + break; + } + + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java index dd926e5..76c0d41 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/adapter/CollageAdapter.java @@ -70,7 +70,6 @@ public CollageItemHolder(View view) public void bind(Genre genre) { - collageContainer.setImageResource(R.drawable.ic_place_holder); genreTextView.setText(genre.getName()); collageLoader.loadCollage(genre.getUrls(), collageContainer); } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java index ff110b4..c92c2da 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandler.java @@ -1,7 +1,7 @@ package ru.yandex.yamblz.handler; -public interface CriticalSectionsHandler { - +public interface CriticalSectionsHandler +{ void startSection(int id); void stopSection(int id); 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..2876ff7 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsManager.java @@ -1,17 +1,21 @@ package ru.yandex.yamblz.handler; -public class CriticalSectionsManager { - +public class CriticalSectionsManager +{ private static CriticalSectionsHandler sCriticalSectionsHandler; - public static void init(CriticalSectionsHandler criticalSectionsHandler) { + public static void init(CriticalSectionsHandler criticalSectionsHandler) + { sCriticalSectionsHandler = criticalSectionsHandler; } - public static CriticalSectionsHandler getHandler() { - if (sCriticalSectionsHandler == null) { + public static CriticalSectionsHandler getHandler() + { + if (sCriticalSectionsHandler == null) + { sCriticalSectionsHandler = new StubCriticalSectionsHandler(); } + return sCriticalSectionsHandler; } } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java new file mode 100644 index 0000000..0db6486 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java @@ -0,0 +1,118 @@ +package ru.yandex.yamblz.handler; + +import android.os.Handler; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by platon on 29.07.2016. + */ +public class SimpleCriticalSectionHandler implements CriticalSectionsHandler +{ + private final ConcurrentHashMap> queue; + private final Set sections; + private final Handler mainHandler; + + public SimpleCriticalSectionHandler(Handler handler) + { + mainHandler = handler; + queue = new ConcurrentHashMap<>(); + sections = new TreeSet<>(); + } + + @Override + public void startSection(int id) + { + sections.add(id); + Iterator>> entryIterator = queue.entrySet().iterator(); + + while (entryIterator.hasNext()) + { + Entry> entry = entryIterator.next(); + if (entry.getKey().equals(id)) + { + entryIterator.remove(); + } + } + } + + @Override + public void stopSection(int id) + { + sections.remove(id); + Iterator>> entryIterator = queue.entrySet().iterator(); + + while (entryIterator.hasNext()) + { + Entry> entry = entryIterator.next(); + if (entry.getKey().equals(id)) + { + for (Task task : entry.getValue()) + { + task.run(); + } + entryIterator.remove(); + } + } + } + + @Override + public void stopSections() + { + sections.clear(); + + for (Entry> entry : queue.entrySet()) + { + for (Task task : entry.getValue()) + { + task.run(); + } + } + + queue.clear(); + } + + @Override + public void postLowPriorityTask(Task task) + { + if (sections.isEmpty() || !sections.contains(task.getId())) + { + mainHandler.post(task::run); + } + else + { + int taskId = task.getId(); + if (queue.containsKey(taskId)) + { + queue.get(taskId).add(task); + } + else + { + List tasks = new ArrayList<>(); + tasks.add(task); + queue.put(taskId, tasks); + } + } + } + + @Override + public void postLowPriorityTaskDelayed(Task task, int delay) {} + + @Override + public void removeLowPriorityTask(Task task) + { + queue.get(task.getId()).remove(task); + } + + @Override + public void removeLowPriorityTasks() + { + queue.clear(); + } +} 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..060f504 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,25 @@ package ru.yandex.yamblz.handler; -public class StubCriticalSectionsHandler implements CriticalSectionsHandler { - +public class StubCriticalSectionsHandler implements CriticalSectionsHandler +{ @Override - public void startSection(int id) { - - } + public void startSection(int id) {} @Override - public void stopSection(int id) { - - } + public void stopSection(int id) {} @Override - public void stopSections() { - - } + public void stopSections() {} @Override - public void postLowPriorityTask(Task task) { - - } + public void postLowPriorityTask(Task task) {} @Override - public void postLowPriorityTaskDelayed(Task task, int delay) { - - } + public void postLowPriorityTaskDelayed(Task task, int delay) {} @Override - public void removeLowPriorityTask(Task task) { - - } + public void removeLowPriorityTask(Task task) {} @Override - public void removeLowPriorityTasks() { - - } + public void removeLowPriorityTasks() {} } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/Task.java b/app/src/main/java/ru/yandex/yamblz/handler/Task.java index 164704c..44c73c0 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/Task.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/Task.java @@ -1,7 +1,7 @@ package ru.yandex.yamblz.handler; -public interface Task { - +public interface Task +{ void run(); - + int getId(); } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java b/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java new file mode 100644 index 0000000..1793aec --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java @@ -0,0 +1,37 @@ +package ru.yandex.yamblz.handler; + +import android.graphics.Bitmap; +import android.util.Log; + +import ru.yandex.yamblz.loader.interfaces.ImageTarget; + +/** + * Created by platon on 29.07.2016. + */ +public class TaskSetImageView implements Task +{ + private static final String TAG = "TaskSetImageView"; + private ImageTarget imageTarget; + private Bitmap bitmap; + private int id; + + public TaskSetImageView(int id, ImageTarget imageTarget, Bitmap bitmap) + { + this.imageTarget = imageTarget; + this.bitmap = bitmap; + this.id = id; + } + + @Override + public void run() + { + Log.d(TAG, "run"); + imageTarget.onLoadBitmap(bitmap); + } + + @Override + public int getId() + { + return id; + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java new file mode 100644 index 0000000..b96ee27 --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java @@ -0,0 +1,100 @@ +package ru.yandex.yamblz.loader; + +import android.graphics.Bitmap; +import android.widget.ImageView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import ru.yandex.yamblz.genre.RecyclerScrollListener; +import ru.yandex.yamblz.handler.CriticalSectionsHandler; +import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.handler.TaskSetImageView; +import ru.yandex.yamblz.loader.interfaces.CollageLoader; +import ru.yandex.yamblz.loader.interfaces.CollageStrategy; +import ru.yandex.yamblz.loader.interfaces.ImageTarget; + +import static ru.yandex.yamblz.genre.RecyclerScrollListener.CS_ID; + +public class CriticalSectionsCollageLoader implements CollageLoader +{ + private static final int DEF_THREAD_COUNT = 4; + private static final int TASK_ID = 1991; + + private final CollageStrategy collageStrategy; + private final LinkedList imageTargets; + private final CriticalSectionsHandler criticalSections; + + public CriticalSectionsCollageLoader() + { + collageStrategy = new CollageStrategyImpl(); + imageTargets = new LinkedList<>(); + criticalSections = CriticalSectionsManager.getHandler(); + } + + @Override + public void loadCollage(List urls, ImageView imageView) + { + ImageTarget imageTarget = new ImageTargetImpl(imageView); + loadCollage(urls, imageTarget); + } + + @Override + public void loadCollage(List urls, ImageTarget imageTarget) + { + loadCollage(urls, imageTarget, collageStrategy); + } + + @Override + public void loadCollage(List urls, ImageView imageView, CollageStrategy strategy) + { + ImageTarget imageTarget = new ImageTargetImpl(imageView); + loadCollage(urls, imageTarget, strategy); + } + + @Override + public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) + { + int threadsCount = urls.size() < DEF_THREAD_COUNT ? 1 : DEF_THREAD_COUNT; + CountDownLatch cdl = new CountDownLatch(threadsCount); + List bitmaps = Collections.synchronizedList(new ArrayList<>()); + ExecutorService downloadExecutor = Executors.newFixedThreadPool(threadsCount); + + clearDuplicate(imageTarget.getImageView()); + imageTargets.push(imageTarget); + + for(int i = 0; i < threadsCount; i++) + { + ImageDownloader imgDownloader = new ImageDownloader(urls.get(i), bitmaps, cdl); + downloadExecutor.execute(imgDownloader); + } + + downloadExecutor.shutdown(); + + new CollageConsumer( + bitmap -> postResult(imageTarget, bitmap), + bitmaps, strategy, cdl).start(); + } + + private void postResult(ImageTarget imageTarget, Bitmap bitmap) + { + criticalSections.postLowPriorityTask(new TaskSetImageView(CS_ID, imageTarget, bitmap)); + } + + private void clearDuplicate(ImageView newImgView) + { + if (newImgView != null) + { + for (ImageTarget it: imageTargets) + { + ImageView cachedImgView = it.getImageView(); + if (cachedImgView!= null && cachedImgView.equals(newImgView)) it.clear(); + } + } + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java index 37393d6..b6e3094 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -3,6 +3,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.graphics.Bitmap; +import android.util.Log; import android.view.animation.AccelerateInterpolator; import android.widget.ImageView; @@ -16,10 +17,14 @@ public class ImageTargetImpl implements ImageTarget { private static final long DURATION = 300; + private static final int EMPTY = 0; + private static final String TAG = "ImageTargetImpl"; + private final WeakReference weakReference; public ImageTargetImpl(ImageView imageView) { + imageView.setImageResource(EMPTY); weakReference = new WeakReference<>(imageView); } @@ -30,6 +35,7 @@ public void onLoadBitmap(Bitmap bitmap) if (imageView != null && bitmap != null) { + Log.d(TAG, "onLoadBitmap"); animateChange(imageView); imageView.setImageBitmap(bitmap); } diff --git a/app/src/main/res/layout/item_genre.xml b/app/src/main/res/layout/item_genre.xml index d3002b2..da08812 100644 --- a/app/src/main/res/layout/item_genre.xml +++ b/app/src/main/res/layout/item_genre.xml @@ -15,6 +15,7 @@ android:layout_width="100dp" android:layout_height="100dp" android:contentDescription="null" + android:background="@drawable/ic_place_holder" android:scaleType="fitCenter" /> Date: Mon, 1 Aug 2016 00:33:49 +0300 Subject: [PATCH 09/13] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0=20postLowPriorityTaskDelayed()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yandex/yamblz/handler/SimpleCriticalSectionHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java index 0db6486..c8a0f8c 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java @@ -102,7 +102,10 @@ public void postLowPriorityTask(Task task) } @Override - public void postLowPriorityTaskDelayed(Task task, int delay) {} + public void postLowPriorityTaskDelayed(Task task, int delay) + { + mainHandler.postDelayed(() -> postLowPriorityTask(task), delay); + } @Override public void removeLowPriorityTask(Task task) From 46b0aa1b9edff6e6c00304ca4d39a15c922115c4 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Tue, 2 Aug 2016 18:37:37 +0300 Subject: [PATCH 10/13] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/SimpleCriticalSectionHandler.java | 57 +++++-------------- .../java/ru/yandex/yamblz/handler/Task.java | 1 - .../yamblz/handler/TaskSetImageView.java | 12 +--- .../loader/CriticalSectionsCollageLoader.java | 42 ++++++++------ .../yandex/yamblz/loader/ImageTargetImpl.java | 2 - 5 files changed, 40 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java index c8a0f8c..94e1f72 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java @@ -3,6 +3,7 @@ import android.os.Handler; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; @@ -15,14 +16,14 @@ */ public class SimpleCriticalSectionHandler implements CriticalSectionsHandler { - private final ConcurrentHashMap> queue; + private final List tasks; private final Set sections; private final Handler mainHandler; public SimpleCriticalSectionHandler(Handler handler) { mainHandler = handler; - queue = new ConcurrentHashMap<>(); + tasks = Collections.synchronizedList(new ArrayList<>()); sections = new TreeSet<>(); } @@ -30,36 +31,19 @@ public SimpleCriticalSectionHandler(Handler handler) public void startSection(int id) { sections.add(id); - Iterator>> entryIterator = queue.entrySet().iterator(); - - while (entryIterator.hasNext()) - { - Entry> entry = entryIterator.next(); - if (entry.getKey().equals(id)) - { - entryIterator.remove(); - } - } } @Override public void stopSection(int id) { sections.remove(id); - Iterator>> entryIterator = queue.entrySet().iterator(); - while (entryIterator.hasNext()) + for (Task task : tasks) { - Entry> entry = entryIterator.next(); - if (entry.getKey().equals(id)) - { - for (Task task : entry.getValue()) - { - task.run(); - } - entryIterator.remove(); - } + mainHandler.post(task::run); } + + removeLowPriorityTasks(); } @Override @@ -67,37 +51,24 @@ public void stopSections() { sections.clear(); - for (Entry> entry : queue.entrySet()) + for (Task task : tasks) { - for (Task task : entry.getValue()) - { - task.run(); - } + mainHandler.post(task::run); } - queue.clear(); + removeLowPriorityTasks(); } @Override public void postLowPriorityTask(Task task) { - if (sections.isEmpty() || !sections.contains(task.getId())) + if (sections.isEmpty()) { mainHandler.post(task::run); } else { - int taskId = task.getId(); - if (queue.containsKey(taskId)) - { - queue.get(taskId).add(task); - } - else - { - List tasks = new ArrayList<>(); - tasks.add(task); - queue.put(taskId, tasks); - } + tasks.add(task); } } @@ -110,12 +81,12 @@ public void postLowPriorityTaskDelayed(Task task, int delay) @Override public void removeLowPriorityTask(Task task) { - queue.get(task.getId()).remove(task); + tasks.remove(task); } @Override public void removeLowPriorityTasks() { - queue.clear(); + tasks.clear(); } } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/Task.java b/app/src/main/java/ru/yandex/yamblz/handler/Task.java index 44c73c0..c75f77c 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/Task.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/Task.java @@ -3,5 +3,4 @@ public interface Task { void run(); - int getId(); } diff --git a/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java b/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java index 1793aec..3332c91 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/TaskSetImageView.java @@ -10,28 +10,18 @@ */ public class TaskSetImageView implements Task { - private static final String TAG = "TaskSetImageView"; private ImageTarget imageTarget; private Bitmap bitmap; - private int id; - public TaskSetImageView(int id, ImageTarget imageTarget, Bitmap bitmap) + public TaskSetImageView(ImageTarget imageTarget, Bitmap bitmap) { this.imageTarget = imageTarget; this.bitmap = bitmap; - this.id = id; } @Override public void run() { - Log.d(TAG, "run"); imageTarget.onLoadBitmap(bitmap); } - - @Override - public int getId() - { - return id; - } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java index b96ee27..7edcfec 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java @@ -5,35 +5,34 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; - -import ru.yandex.yamblz.genre.RecyclerScrollListener; import ru.yandex.yamblz.handler.CriticalSectionsHandler; import ru.yandex.yamblz.handler.CriticalSectionsManager; +import ru.yandex.yamblz.handler.Task; import ru.yandex.yamblz.handler.TaskSetImageView; import ru.yandex.yamblz.loader.interfaces.CollageLoader; import ru.yandex.yamblz.loader.interfaces.CollageStrategy; import ru.yandex.yamblz.loader.interfaces.ImageTarget; -import static ru.yandex.yamblz.genre.RecyclerScrollListener.CS_ID; - public class CriticalSectionsCollageLoader implements CollageLoader { private static final int DEF_THREAD_COUNT = 4; - private static final int TASK_ID = 1991; private final CollageStrategy collageStrategy; - private final LinkedList imageTargets; + private final List imageTargets; + private final LinkedList executors; private final CriticalSectionsHandler criticalSections; public CriticalSectionsCollageLoader() { collageStrategy = new CollageStrategyImpl(); - imageTargets = new LinkedList<>(); + imageTargets = Collections.synchronizedList(new LinkedList<>()); + executors = new LinkedList<>(); criticalSections = CriticalSectionsManager.getHandler(); } @@ -66,34 +65,43 @@ public void loadCollage(List urls, ImageTarget imageTarget, CollageStrat ExecutorService downloadExecutor = Executors.newFixedThreadPool(threadsCount); clearDuplicate(imageTarget.getImageView()); - imageTargets.push(imageTarget); + imageTargets.add(imageTarget); + executors.push(downloadExecutor); - for(int i = 0; i < threadsCount; i++) + for (int i = 0; i < threadsCount; i++) { ImageDownloader imgDownloader = new ImageDownloader(urls.get(i), bitmaps, cdl); downloadExecutor.execute(imgDownloader); } - downloadExecutor.shutdown(); - - new CollageConsumer( + CollageConsumer collageConsumer = new CollageConsumer( bitmap -> postResult(imageTarget, bitmap), - bitmaps, strategy, cdl).start(); + bitmaps, strategy, cdl); + + downloadExecutor.execute(collageConsumer); + downloadExecutor.shutdown(); } private void postResult(ImageTarget imageTarget, Bitmap bitmap) { - criticalSections.postLowPriorityTask(new TaskSetImageView(CS_ID, imageTarget, bitmap)); + criticalSections.postLowPriorityTask(new TaskSetImageView(imageTarget, bitmap)); } private void clearDuplicate(ImageView newImgView) { if (newImgView != null) { - for (ImageTarget it: imageTargets) + Iterator iterator = imageTargets.iterator(); + while (iterator.hasNext()) { - ImageView cachedImgView = it.getImageView(); - if (cachedImgView!= null && cachedImgView.equals(newImgView)) it.clear(); + ImageTarget cachedImageTarget = iterator.next(); + ImageView cachedImgView = cachedImageTarget.getImageView(); + if (cachedImgView!= null && cachedImgView.equals(newImgView)) + { + cachedImageTarget.clear(); + executors.pollLast().shutdownNow(); + iterator.remove(); + } } } } diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java index b6e3094..28027a5 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageTargetImpl.java @@ -18,7 +18,6 @@ public class ImageTargetImpl implements ImageTarget { private static final long DURATION = 300; private static final int EMPTY = 0; - private static final String TAG = "ImageTargetImpl"; private final WeakReference weakReference; @@ -35,7 +34,6 @@ public void onLoadBitmap(Bitmap bitmap) if (imageView != null && bitmap != null) { - Log.d(TAG, "onLoadBitmap"); animateChange(imageView); imageView.setImageBitmap(bitmap); } From 0e8fa4d6cbe8bf0377365880e30dc54d7e3ece1f Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Tue, 2 Aug 2016 18:51:06 +0300 Subject: [PATCH 11/13] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/SimpleCriticalSectionHandler.java | 7 +++- .../loader/CriticalSectionsCollageLoader.java | 38 ++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java index 94e1f72..2de76fc 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java @@ -81,7 +81,12 @@ public void postLowPriorityTaskDelayed(Task task, int delay) @Override public void removeLowPriorityTask(Task task) { - tasks.remove(task); + Iterator iterator = tasks.iterator(); + while (iterator.hasNext()) + { + if (iterator.next().equals(task)) iterator.remove(); + break; + } } @Override diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java index 7edcfec..a191513 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java @@ -59,27 +59,31 @@ public void loadCollage(List urls, ImageView imageView, CollageStrategy @Override public void loadCollage(List urls, ImageTarget imageTarget, CollageStrategy strategy) { - int threadsCount = urls.size() < DEF_THREAD_COUNT ? 1 : DEF_THREAD_COUNT; - CountDownLatch cdl = new CountDownLatch(threadsCount); - List bitmaps = Collections.synchronizedList(new ArrayList<>()); - ExecutorService downloadExecutor = Executors.newFixedThreadPool(threadsCount); + if (urls.size() != 0) + { + int threadsCount = urls.size() < DEF_THREAD_COUNT ? 1 : DEF_THREAD_COUNT; - clearDuplicate(imageTarget.getImageView()); - imageTargets.add(imageTarget); - executors.push(downloadExecutor); + CountDownLatch cdl = new CountDownLatch(threadsCount); + List bitmaps = Collections.synchronizedList(new ArrayList<>()); + ExecutorService downloadExecutor = Executors.newFixedThreadPool(threadsCount); - for (int i = 0; i < threadsCount; i++) - { - ImageDownloader imgDownloader = new ImageDownloader(urls.get(i), bitmaps, cdl); - downloadExecutor.execute(imgDownloader); - } + clearDuplicate(imageTarget.getImageView()); + imageTargets.add(imageTarget); + executors.push(downloadExecutor); - CollageConsumer collageConsumer = new CollageConsumer( - bitmap -> postResult(imageTarget, bitmap), - bitmaps, strategy, cdl); + for (int i = 0; i < threadsCount; i++) + { + ImageDownloader imgDownloader = new ImageDownloader(urls.get(i), bitmaps, cdl); + downloadExecutor.execute(imgDownloader); + } + + CollageConsumer collageConsumer = new CollageConsumer( + bitmap -> postResult(imageTarget, bitmap), + bitmaps, strategy, cdl); - downloadExecutor.execute(collageConsumer); - downloadExecutor.shutdown(); + downloadExecutor.execute(collageConsumer); + downloadExecutor.shutdown(); + } } private void postResult(ImageTarget imageTarget, Bitmap bitmap) From 0aa471075bf552574443851a865c44619ad87b52 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Tue, 2 Aug 2016 21:05:09 +0300 Subject: [PATCH 12/13] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/SimpleCriticalSectionHandler.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java index 2de76fc..2b77f39 100644 --- a/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java +++ b/app/src/main/java/ru/yandex/yamblz/handler/SimpleCriticalSectionHandler.java @@ -1,6 +1,7 @@ package ru.yandex.yamblz.handler; import android.os.Handler; +import android.util.Log; import java.util.ArrayList; import java.util.Collections; @@ -40,7 +41,8 @@ public void stopSection(int id) for (Task task : tasks) { - mainHandler.post(task::run); + if (sections.isEmpty()) mainHandler.post(task::run); + else break; } removeLowPriorityTasks(); @@ -53,7 +55,8 @@ public void stopSections() for (Task task : tasks) { - mainHandler.post(task::run); + if (sections.isEmpty()) mainHandler.post(task::run); + else break; } removeLowPriorityTasks(); @@ -62,14 +65,8 @@ public void stopSections() @Override public void postLowPriorityTask(Task task) { - if (sections.isEmpty()) - { - mainHandler.post(task::run); - } - else - { - tasks.add(task); - } + if (sections.isEmpty()) mainHandler.post(task::run); + else tasks.add(task); } @Override From dae15a8ba9acbe5ab08be73a6eccad91f25ea0f9 Mon Sep 17 00:00:00 2001 From: Valentin Postnov Date: Sat, 13 Aug 2016 19:54:37 +0300 Subject: [PATCH 13/13] ref --- app/src/main/java/ru/yandex/yamblz/App.java | 14 ++++ .../yandex/yamblz/genre/GenresFragment.java | 24 +------ .../yamblz/genre/GenresPresenterImpl.java | 10 +-- .../yamblz/genre/data/source/Cache.java | 11 --- .../yamblz/genre/data/source/CacheImpl.java | 69 ------------------- .../yamblz/genre/data/source/DataSource.java | 4 +- .../genre/data/source/RemoteDataSource.java | 9 ++- .../yamblz/genre/data/source/Repository.java | 28 ++++---- .../genre/data/source/local/CacheImpl.java | 55 +++++++++++++++ .../genre/data/source/local/FileManager.java | 58 ++++++++++++++++ .../genre/data/source/local/ICache.java | 14 ++++ .../data/source/local/JsonSerializer.java | 26 +++++++ .../loader/CriticalSectionsCollageLoader.java | 2 +- .../yandex/yamblz/loader/ImageDownloader.java | 10 +-- dependencies.gradle | 2 +- 15 files changed, 203 insertions(+), 133 deletions(-) delete mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java delete mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/local/CacheImpl.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/local/FileManager.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/local/ICache.java create mode 100644 app/src/main/java/ru/yandex/yamblz/genre/data/source/local/JsonSerializer.java diff --git a/app/src/main/java/ru/yandex/yamblz/App.java b/app/src/main/java/ru/yandex/yamblz/App.java index c13a0a6..d224ea0 100644 --- a/app/src/main/java/ru/yandex/yamblz/App.java +++ b/app/src/main/java/ru/yandex/yamblz/App.java @@ -7,6 +7,11 @@ import ru.yandex.yamblz.developer_settings.DevMetricsProxy; import ru.yandex.yamblz.developer_settings.DeveloperSettingsModel; +import ru.yandex.yamblz.genre.data.source.DataSource; +import ru.yandex.yamblz.genre.data.source.RemoteDataSource; +import ru.yandex.yamblz.genre.data.source.Repository; +import ru.yandex.yamblz.genre.data.source.local.CacheImpl; +import ru.yandex.yamblz.genre.data.source.local.JsonSerializer; import ru.yandex.yamblz.genre.util.NetworkManager; import ru.yandex.yamblz.handler.CriticalSectionsManager; import ru.yandex.yamblz.handler.SimpleCriticalSectionHandler; @@ -18,6 +23,7 @@ public class App extends Application { private ApplicationComponent applicationComponent; + private DataSource artistRepository; // Prevent need in a singleton (global) reference to the application object. @NonNull @@ -44,6 +50,9 @@ public void onCreate() } NetworkManager.init(getApplicationContext()); + artistRepository = new Repository( + new CacheImpl(getCacheDir(), new JsonSerializer()), + new RemoteDataSource()); // первое задание, раскомментировать //CollageLoaderManager.init(new SimpleCollageLoader(new Handler(getMainLooper()))); @@ -65,4 +74,9 @@ public ApplicationComponent applicationComponent() { return applicationComponent; } + + public DataSource getArtistRepository() + { + return artistRepository; + } } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java index ab518f4..039ffd7 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresFragment.java @@ -17,12 +17,11 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.Unbinder; +import ru.yandex.yamblz.App; import ru.yandex.yamblz.R; import ru.yandex.yamblz.genre.adapter.CollageAdapter; import ru.yandex.yamblz.genre.data.entity.Artist; import ru.yandex.yamblz.genre.data.entity.Genre; -import ru.yandex.yamblz.genre.data.source.Cache; -import ru.yandex.yamblz.genre.data.source.CacheImpl; import ru.yandex.yamblz.genre.data.source.DataSource; import ru.yandex.yamblz.genre.data.source.RemoteDataSource; import ru.yandex.yamblz.genre.data.source.Repository; @@ -32,11 +31,8 @@ public class GenresFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener, GenresView { - private static final String TAG = "GenresFragment"; - private GenresPresenter presenter; private CollageAdapter collageAdapter; - private Unbinder unbinder; @BindView(R.id.rv_collages) RecyclerView recyclerView; @@ -47,21 +43,14 @@ public class GenresFragment extends BaseFragment implements SwipeRefreshLayout.O public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - File cacheDir = getActivity().getCacheDir(); - Cache cache = new CacheImpl(cacheDir); - DataSource remoteDataSource = new RemoteDataSource(); - - presenter = new GenresPresenterImpl(Repository.getInstance(cache, remoteDataSource)); + presenter = new GenresPresenterImpl(App.get(getContext()).getArtistRepository()); } @NonNull @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle bundle) { - View view = inflater.inflate(R.layout.fragment_content, container, false); - unbinder = ButterKnife.bind(this, view); - return view; + return inflater.inflate(R.layout.fragment_content, container, false); } @Override @@ -91,13 +80,6 @@ public void onPause() presenter.unbind(); } - @Override - public void onDestroyView() - { - unbinder.unbind(); - super.onDestroyView(); - } - @Override public void showProgress(boolean show) { diff --git a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java index 3558cb4..efc517e 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/GenresPresenterImpl.java @@ -39,15 +39,13 @@ public void getGenres(boolean forceLoad) genresView.showProgress(true); if (forceLoad) dataSource.delete(); - subscriptions.add(dataSource.getList() + subscriptions.add(dataSource.getGenres() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .map(Utils::transformArtistToGenres) .subscribe(onNext, onError)); } else { - genresView.showProgress(false); genresView.showError("no connection"); } } @@ -70,12 +68,14 @@ public void unsubscribe() subscriptions.clear(); } - private Action1> onNext = genres -> { + private Action1> onNext = genres -> + { genresView.showProgress(false); genresView.showGenres(genres); }; - private Action1 onError = e -> { + private Action1 onError = e -> + { genresView.showProgress(false); genresView.showError(e.getMessage()); }; diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java deleted file mode 100644 index 8725bbf..0000000 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/source/Cache.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.yandex.yamblz.genre.data.source; - -import java.util.List; - -public interface Cache -{ - List get(); - void put(List list); - boolean clear(); - boolean isEmpty(); -} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java deleted file mode 100644 index e1e6ac1..0000000 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/source/CacheImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -package ru.yandex.yamblz.genre.data.source; - -import android.annotation.SuppressLint; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.List; - -import ru.yandex.yamblz.genre.data.entity.Artist; - -public class CacheImpl implements Cache -{ - private final File cachedFile; - - public CacheImpl(File cacheDir, String name) - { - cachedFile = new File(cacheDir, name); - } - - public CacheImpl(File cacheDir) - { - this(cacheDir, "artists.list"); - } - - @SuppressLint("NewApi") - @Override - public List get() - { - try (FileInputStream is = new FileInputStream(cachedFile); ObjectInputStream in = new ObjectInputStream(is)) - { - return (List) in.readObject(); - } - catch (ClassNotFoundException | IOException e) - { - e.printStackTrace(); - return null; - } - } - - @SuppressLint("NewApi") - @Override - public void put(List list) - { - try (FileOutputStream os = new FileOutputStream(cachedFile); ObjectOutputStream out = new ObjectOutputStream(os)) - { - out.writeObject(list); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - @Override - public boolean clear() - { - return cachedFile.delete(); - } - - @Override - public boolean isEmpty() - { - return !cachedFile.exists(); - } -} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java index 0010266..138b323 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/DataSource.java @@ -3,6 +3,7 @@ import java.util.List; import ru.yandex.yamblz.genre.data.entity.Artist; +import ru.yandex.yamblz.genre.data.entity.Genre; import rx.Observable; /** @@ -10,6 +11,7 @@ */ public interface DataSource { - Observable> getList(); + Observable> getArtists(); + Observable> getGenres(); void delete(); } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java index 6d5c6d3..881f0d7 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/RemoteDataSource.java @@ -7,6 +7,7 @@ import retrofit2.converter.gson.GsonConverterFactory; import ru.yandex.yamblz.genre.api.ArtistsApi; import ru.yandex.yamblz.genre.data.entity.Artist; +import ru.yandex.yamblz.genre.data.entity.Genre; import rx.Observable; public class RemoteDataSource implements DataSource @@ -26,11 +27,17 @@ public RemoteDataSource() } @Override - public Observable> getList() + public Observable> getArtists() { return api.listArtists(); } + @Override + public Observable> getGenres() + { + return null; + } + @Override public void delete() {} } diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java index 6780b2b..99ba931 100644 --- a/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/Repository.java @@ -3,6 +3,9 @@ import java.util.List; import ru.yandex.yamblz.genre.data.entity.Artist; +import ru.yandex.yamblz.genre.data.entity.Genre; +import ru.yandex.yamblz.genre.data.source.local.ICache; +import ru.yandex.yamblz.genre.util.Utils; import rx.Observable; /** @@ -10,33 +13,28 @@ */ public class Repository implements DataSource { - private static Repository sRepository; - - private Cache cache; + private ICache cache; private DataSource remote; - public static Repository getInstance(Cache cache, DataSource remote) - { - if (sRepository == null) - { - sRepository = new Repository(cache, remote); - } - return sRepository; - } - - private Repository(Cache cache, DataSource remote) + public Repository(ICache cache, DataSource remote) { this.cache = cache; this.remote = remote; } @Override - public Observable> getList() + public Observable> getArtists() { if (cache.isEmpty()) return fromRemote(); return fromLocal(); } + @Override + public Observable> getGenres() + { + return getArtists().map(Utils::transformArtistToGenres); + } + @Override public void delete() { @@ -45,7 +43,7 @@ public void delete() private Observable> fromRemote() { - return remote.getList().doOnNext(artists -> cache.put(artists)); + return remote.getArtists().doOnNext(artists -> cache.put(artists)); } private Observable> fromLocal() diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/CacheImpl.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/CacheImpl.java new file mode 100644 index 0000000..e862b2e --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/CacheImpl.java @@ -0,0 +1,55 @@ +package ru.yandex.yamblz.genre.data.source.local; + + +import java.io.File; +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Artist; + + +/** + * Created by platon on 19.07.2016. + */ +public class CacheImpl implements ICache +{ + private final File cachedFile; + private final JsonSerializer serializer; + private final FileManager fileManager; + + public CacheImpl(File cacheDir, String name, JsonSerializer artistCacheSerializer) + { + cachedFile = new File(cacheDir, name); + fileManager = new FileManager(); + serializer = artistCacheSerializer; + } + + public CacheImpl(File cacheDir, JsonSerializer artistCacheSerializer) + { + this(cacheDir, "artists.list", artistCacheSerializer); + } + + @Override + public List get() + { + String json = fileManager.readFileContent(cachedFile); + return serializer.deserialize(json); + } + + @Override + public void put(List list) + { + fileManager.writeToFile(cachedFile, serializer.serialize(list)); + } + + @Override + public boolean clear() + { + return cachedFile.delete(); + } + + @Override + public boolean isEmpty() + { + return !cachedFile.exists(); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/FileManager.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/FileManager.java new file mode 100644 index 0000000..486156b --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/FileManager.java @@ -0,0 +1,58 @@ +package ru.yandex.yamblz.genre.data.source.local; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Created by platon on 10.08.2016. + */ +public class FileManager +{ + public void writeToFile(File file, String fileContent) + { + if (!file.exists()) + { + try + { + FileWriter writer = new FileWriter(file); + writer.write(fileContent); + writer.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + public String readFileContent(File file) + { + StringBuilder fileContentBuilder = new StringBuilder(); + if (file.exists()) + { + String stringLine; + try + { + FileReader fileReader = new FileReader(file); + BufferedReader bufferedReader = new BufferedReader(fileReader); + + while ((stringLine = bufferedReader.readLine()) != null) + { + fileContentBuilder.append(stringLine).append("\n"); + } + + bufferedReader.close(); + fileReader.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + return fileContentBuilder.toString(); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/ICache.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/ICache.java new file mode 100644 index 0000000..212b63a --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/ICache.java @@ -0,0 +1,14 @@ +package ru.yandex.yamblz.genre.data.source.local; + +import java.util.List; + +/** + * Created by platon on 19.07.2016. + */ +public interface ICache +{ + List get(); + void put(List list); + boolean clear(); + boolean isEmpty(); +} diff --git a/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/JsonSerializer.java b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/JsonSerializer.java new file mode 100644 index 0000000..4fa732d --- /dev/null +++ b/app/src/main/java/ru/yandex/yamblz/genre/data/source/local/JsonSerializer.java @@ -0,0 +1,26 @@ +package ru.yandex.yamblz.genre.data.source.local; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.util.List; + +import ru.yandex.yamblz.genre.data.entity.Artist; + +/** + * Created by platon on 10.08.2016. + */ +public class JsonSerializer +{ + private final Gson gson = new Gson(); + + public String serialize(List artist) + { + return gson.toJson(artist); + } + + public List deserialize(String jsonString) + { + return gson.fromJson(jsonString, new TypeToken>() {}.getType()); + } +} diff --git a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java index a191513..cbcf970 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/CriticalSectionsCollageLoader.java @@ -11,9 +11,9 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; + import ru.yandex.yamblz.handler.CriticalSectionsHandler; import ru.yandex.yamblz.handler.CriticalSectionsManager; -import ru.yandex.yamblz.handler.Task; import ru.yandex.yamblz.handler.TaskSetImageView; import ru.yandex.yamblz.loader.interfaces.CollageLoader; import ru.yandex.yamblz.loader.interfaces.CollageStrategy; diff --git a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java index bcf4079..2f11a04 100644 --- a/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java +++ b/app/src/main/java/ru/yandex/yamblz/loader/ImageDownloader.java @@ -40,14 +40,8 @@ public ImageDownloader(String url, List bitmaps, CountDownLatch countDow @Override public void run() { - if (bitmapCache.get(url) != null) - { - bitmaps.add(cachedBitmap()); - } - else - { - bitmaps.add(remoteBitmap()); - } + if (bitmapCache.get(url) != null) bitmaps.add(cachedBitmap()); + else bitmaps.add(remoteBitmap()); countDownLatch.countDown(); } diff --git a/dependencies.gradle b/dependencies.gradle index 9bd0211..638b881 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,7 +7,7 @@ ext.versions = [ compileSdk : 23, buildTools : '23.0.3', - androidGradlePlugin : '2.2.0-alpha4', + androidGradlePlugin : '2.2.0-alpha7', aptGradlePlugin : '1.8', retrolambdaGradlePlugin : '3.2.5', lombokGradlePlugin : '0.2.3.a2',