-
Notifications
You must be signed in to change notification settings - Fork 20
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
AudasViator
wants to merge
17
commits into
yamblz-native:master
Choose a base branch
from
AudasViator:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
333e43b
Сделалось множество с ключём String и значением Set<Artist>
AudasViator 739f718
Тест rx и многопоточности
AudasViator dac3e1a
rx
AudasViator 989c2b7
Коллаж собирается, осталось сделать всё остальное
AudasViator 672b98d
Формально работает, на деле надо переписать
AudasViator ffc06d1
Loader готов
AudasViator 44f971e
Чуть-чуть критических секций
AudasViator 5bc9a4c
Ща всё сделаем нормально
AudasViator 75789ac
Ща всё сделаем нормально (2)
AudasViator 62a287b
Ща всё сделаем нормально (3)
AudasViator 6b34434
Ща всё сделаем нормально (4)
AudasViator e87c0ff
Готово
AudasViator 3ffc21d
Забыл убрать okhttp
AudasViator 03880ee
Ой, я же использую okhttp
AudasViator 3f91d3b
Исправлены критические секции, убран лишний код из загрузчика коллажей
AudasViator 748f55e
Вечная борьба с git add .
AudasViator 01a20aa
Убран костыль ImageTargetWithId, вместно него всего-лишь переопределё…
AudasViator File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
app/src/main/java/ru/yandex/yamblz/handler/CriticalSectionsHandlerImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
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); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 0 additions & 39 deletions
39
app/src/main/java/ru/yandex/yamblz/handler/StubCriticalSectionsHandler.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() { | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 0 additions & 31 deletions
31
app/src/main/java/ru/yandex/yamblz/loader/StubCollageLoader.java
This file was deleted.
Oops, something went wrong.
133 changes: 133 additions & 0 deletions
133
app/src/main/java/ru/yandex/yamblz/loader/square/CollageLoaderSquare.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
app/src/main/java/ru/yandex/yamblz/loader/square/CollageStrategySquare.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А запустить таски из очереди?