Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alexander Vasin (prieran) vs rx #10

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
333e43b
Сделалось множество с ключём String и значением Set<Artist>
AudasViator Jul 27, 2016
739f718
Тест rx и многопоточности
AudasViator Jul 27, 2016
dac3e1a
rx
AudasViator Jul 28, 2016
989c2b7
Коллаж собирается, осталось сделать всё остальное
AudasViator Jul 29, 2016
672b98d
Формально работает, на деле надо переписать
AudasViator Jul 30, 2016
ffc06d1
Loader готов
AudasViator Jul 31, 2016
44f971e
Чуть-чуть критических секций
AudasViator Jul 31, 2016
5bc9a4c
Ща всё сделаем нормально
AudasViator Aug 1, 2016
75789ac
Ща всё сделаем нормально (2)
AudasViator Aug 1, 2016
62a287b
Ща всё сделаем нормально (3)
AudasViator Aug 1, 2016
6b34434
Ща всё сделаем нормально (4)
AudasViator Aug 2, 2016
e87c0ff
Готово
AudasViator Aug 2, 2016
3ffc21d
Забыл убрать okhttp
AudasViator Aug 2, 2016
03880ee
Ой, я же использую okhttp
AudasViator Aug 2, 2016
3f91d3b
Исправлены критические секции, убран лишний код из загрузчика коллажей
AudasViator Aug 6, 2016
748f55e
Вечная борьба с git add .
AudasViator Aug 6, 2016
01a20aa
Убран костыль ImageTargetWithId, вместно него всего-лишь переопределё…
AudasViator Aug 9, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ dependencies {
compile libraries.dagger
apt libraries.daggerCompiler

compile libraries.rxjava
compile libraries.rxandroid

compile libraries.gson
compile libraries.okhttp
compile libraries.picasso

compile libraries.supportAnnotations
compile libraries.supportAppCompat
compile libraries.supportDesign
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/ru/yandex/yamblz/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void onCreate() {
}

CollageLoaderManager.init(null); // add implementation
CriticalSectionsManager.init(null); // add implementation
//CriticalSectionsManager.init(null); // add implementation
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ru.yandex.yamblz.handler;


import android.os.Handler;
import android.os.Looper;
import android.util.SparseIntArray;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

public class CriticalSectionsHandlerImpl implements CriticalSectionsHandler {
private Handler mHandler;
private Queue<Task> mTaskQueue;
private SparseIntArray mSectionArray;

public CriticalSectionsHandlerImpl() {
mHandler = new Handler(Looper.getMainLooper());
mTaskQueue = new LinkedBlockingQueue<>();
mSectionArray = new SparseIntArray();
}

@Override
public void startSection(int id) {
mSectionArray.append(id, 1);
}

@Override
public void stopSection(int id) {
mSectionArray.delete(id);
doNext();
}


@Override
public void stopSections() {
mSectionArray.clear();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А запустить таски из очереди?

doNext();
}

@Override
public void postLowPriorityTask(Task task) {
if (mSectionArray.size() != 0) {
mTaskQueue.add(task);
} else {
mHandler.post(task::run);
}
}

@Override
public void postLowPriorityTaskDelayed(Task task, int delay) {
if (mSectionArray.size() != 0) {
mTaskQueue.add(task);
} else {
mHandler.postDelayed(task::run, delay);
}
}

@Override
public void removeLowPriorityTask(Task task) {
mHandler.removeCallbacks(task::run);
}

@Override
public void removeLowPriorityTasks() {
while (!mTaskQueue.isEmpty()) {
mHandler.removeCallbacks(mTaskQueue.poll()::run);
}
}

private void doNext() {
if (mSectionArray.size() == 0) {
Task task = mTaskQueue.poll();
if (task != null) {
Task anotherTask = () -> {
task.run();
doNext();
};
mHandler.post(anotherTask::run);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public static void init(CriticalSectionsHandler criticalSectionsHandler) {

public static CriticalSectionsHandler getHandler() {
if (sCriticalSectionsHandler == null) {
sCriticalSectionsHandler = new StubCriticalSectionsHandler();
sCriticalSectionsHandler = new CriticalSectionsHandlerImpl();
}
return sCriticalSectionsHandler;
}
}
}

This file was deleted.

9 changes: 9 additions & 0 deletions app/src/main/java/ru/yandex/yamblz/handler/TaskImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ru.yandex.yamblz.handler;


public class TaskImpl implements Task {
@Override
public void run() {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static void init(CollageLoader collageLoader) {

public static CollageLoader getLoader() {
if (sCollageLoader == null) {
sCollageLoader = new StubCollageLoader();
throw new RuntimeException("Надо было инициализировать");
}
return sCollageLoader;
}
Expand Down
31 changes: 0 additions & 31 deletions app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package ru.yandex.yamblz.loader.square;

import android.graphics.Bitmap;
import android.util.SparseArray;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import ru.yandex.yamblz.loader.CollageLoader;
import ru.yandex.yamblz.loader.CollageStrategy;
import ru.yandex.yamblz.loader.ImageTarget;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class CollageLoaderSquare implements CollageLoader {
private static final int NUMBER_OF_THREADS = 2;
private final CollageStrategySquare DEFAULT_COLLAGE_STRATEGY = new CollageStrategySquare();
private final Picasso mPicasso;
private final SparseArray<Subscription> mSubscriptionMap = new SparseArray<>(); // Хранит подписки

public CollageLoaderSquare(Picasso picasso) {
mPicasso = picasso;
}

@Override
public void loadCollage(List<String> urls, ImageView imageView) {
loadCollage(urls, imageView, DEFAULT_COLLAGE_STRATEGY);
}

@Override
public void loadCollage(List<String> urls, ImageTarget imageTarget) {
loadCollage(urls, imageTarget, DEFAULT_COLLAGE_STRATEGY);
}

@Override
public void loadCollage(List<String> urls, ImageView imageView, CollageStrategy collageStrategy) {
WeakReference<ImageView> imageViewWeakReference = new WeakReference<>(imageView);
ImageTarget imageTarget = new ImageTarget() {
@Override
public void onLoadBitmap(Bitmap bitmap) {
ImageView targetImageView = imageViewWeakReference.get();
if (targetImageView != null) {
targetImageView.setImageBitmap(bitmap);
}
}

@Override
public int hashCode() { // Раньше тут был костыль, но теперь его нет
ImageView targetImageView = imageViewWeakReference.get();
if (targetImageView != null) {
return targetImageView.hashCode();
} else {
return 0;
}
}
};

loadCollage(urls, imageTarget, collageStrategy);
}

@Override
public void loadCollage(List<String> urls, ImageTarget imageTarget, CollageStrategy collageStrategy) {
int imageTargetId = imageTarget.hashCode();

Subscription subscription = mSubscriptionMap.get(imageTargetId);
if (subscription != null) {
subscription.unsubscribe();
}

Action1<Bitmap> onCreateCollage = imageTarget::onLoadBitmap;

Subscription newSubscription = makeCollage(urls, onCreateCollage, collageStrategy);
mSubscriptionMap.put(imageTargetId, newSubscription);
}

private Subscription makeCollage(List<String> urls, Action1<Bitmap> onCreateCollage, CollageStrategy collageStrategy) {
final AtomicInteger counter = new AtomicInteger();
final List<Bitmap> bitmapList = new CopyOnWriteArrayList<>(); // Скорость?..
// Чистим за собой
// onComplete после unsubscribe не вызывается, но GC всё равно всё собирает
final Action0 clearBitmaps = () -> {
for (Bitmap bitmap : bitmapList) {
bitmap.recycle();
}
};

return Observable.from(urls)
.groupBy(s -> counter.getAndIncrement() % NUMBER_OF_THREADS) // Делим на NUMBER_OF_THREADS потоков
.flatMap(g -> g.subscribeOn(Schedulers.newThread())) // Грузим картинки (вроде) параллельно
.map(this::downloadImage) // Превращаем String в Bitmap
.filter(b -> b != null) // Выкидываем незагрузившиеся
.flatMap(new Func1<Bitmap, Observable<List<Bitmap>>>() { // Превращаем Bitmap в List для CollageStrategy
@Override
public Observable<List<Bitmap>> call(Bitmap bitmap) {
bitmapList.add(bitmap);
return Observable.just(bitmapList);
}
})
.filter(list -> Math.round(Math.sqrt(list.size())) == Math.sqrt(list.size())) // Будем делать коллаж каждые 1, 4, 9, 25, 36... картинок, дабы было квадратненько
.sample(1, TimeUnit.SECONDS)
.map(list -> list.subList(0, (int) Math.pow(Math.floor(Math.sqrt(list.size())), 2))) // См. ниже
.flatMap(list -> Observable.just(collageStrategy.create(list))) // Собсно делаем коллаж
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onCreateCollage, Throwable::printStackTrace, clearBitmaps); // Обработка ошибок напргяает
// Проблема с sample (да и вообще со всем кодом выше) в том, что он не даёт Observable отправлять список битмапов чаще, чем раз в секунду
// Однако до него есть оператор flatMap, который всё время что-то добавляет в этот список
// В итоге коллаж делается не из 1, 4, 9... картинок, а из сколько выйдет
// Поэтому приходится брать корень из list.size(), округлять его вниз и возводить в квадрат
// В качестве выхода можно было бы отправлять в CollageStrategy Observable<Bitmap> и пусть он там сам обпроверяется, но интерфейсы трогать негоже
}

// Picasso кеширует картинки на диск, скажем ей спасибо
private Bitmap downloadImage(String url) {
try {
return mPicasso.load(url).get();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ru.yandex.yamblz.loader.square;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;

import java.util.List;

import ru.yandex.yamblz.loader.CollageStrategy;

public class CollageStrategySquare implements CollageStrategy {
private static final int COLLAGE_SIZE = 1500;

@Override
public Bitmap create(List<Bitmap> bitmaps) {
if (bitmaps == null || bitmaps.size() == 0) {
return null; // Нечего на вход ерунду подавать
}

int pictureSize = (int) Math.floor(COLLAGE_SIZE / Math.sqrt(bitmaps.size())); // В меньшую сторону
int realCollageSize = (int) (pictureSize * Math.ceil(Math.sqrt(bitmaps.size()))); // В большую сторону

Bitmap collage = Bitmap.createBitmap(realCollageSize, realCollageSize, Bitmap.Config.ARGB_4444);

Canvas canvas = new Canvas(collage);
int top = 0, left = 0;
for (Bitmap currentBitmap : bitmaps) {
if (left >= realCollageSize) {
left = 0;
top += pictureSize;
}

int currentBitmapSize;
if (currentBitmap.getHeight() < currentBitmap.getWidth()) {
currentBitmapSize = currentBitmap.getHeight();
} else {
currentBitmapSize = currentBitmap.getWidth();
}

canvas.drawBitmap(currentBitmap, new Rect(0, 0, currentBitmapSize, currentBitmapSize),
new Rect(left, top, left + pictureSize, top + pictureSize), null);
left += pictureSize;
}

canvas.save();
return collage;
}
}
Loading