Skip to content

Commit 0a2e282

Browse files
authored
#104 - Add support for redrawing plots inside recyclerview + example (#113)
1 parent b365c63 commit 0a2e282

11 files changed

Lines changed: 397 additions & 222 deletions

File tree

androidplot-core/src/main/java/com/androidplot/Plot.java

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ public enum RenderMode {
212212
* that is being used.
213213
*/
214214
private static class BufferedCanvas {
215+
private int lastHeight = 0;
216+
private int lastWidth = 0;
215217
private volatile Bitmap bgBuffer; // all drawing is done on this buffer.
216218
private volatile Bitmap fgBuffer;
217219
private Canvas canvas = new Canvas();
@@ -226,11 +228,21 @@ public synchronized void swap() {
226228
fgBuffer = tmp;
227229
}
228230

231+
/**
232+
* Used when rendering in background mode and a view is attached
233+
* but not resized, so that rendering buffers will be reinitialized.
234+
*/
235+
public void resizeToLast() {
236+
resize(lastHeight, lastWidth);
237+
}
238+
229239
public synchronized void resize(int h, int w) {
230240
if (w <= 0 || h <= 0) {
231241
bgBuffer = null;
232242
fgBuffer = null;
233243
} else {
244+
lastHeight = h;
245+
lastWidth = w;
234246
try {
235247
bgBuffer = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
236248
fgBuffer = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
@@ -408,35 +420,43 @@ protected final void init(Context context, AttributeSet attrs, int defStyle) {
408420

409421
layoutManager.onPostInit();
410422
if (renderMode == RenderMode.USE_BACKGROUND_THREAD) {
411-
renderThread = new Thread(new Runnable() {
412-
@Override
413-
public void run() {
414-
415-
keepRunning = true;
416-
while (keepRunning) {
417-
isIdle = false;
418-
synchronized (pingPong) {
419-
Canvas c = pingPong.getCanvas();
420-
renderOnCanvas(c);
421-
pingPong.swap();
422-
}
423-
synchronized (renderSync) {
424-
postInvalidate();
425-
// prevent this thread from becoming an orphan
426-
// after the view is destroyed
427-
if (keepRunning) {
428-
try {
429-
renderSync.wait();
430-
} catch (InterruptedException e) {
431-
keepRunning = false;
432-
}
433-
}
423+
startBackgroundRendering();
424+
}
425+
}
426+
427+
protected void startBackgroundRendering() {
428+
if(renderThread != null) {
429+
return;
430+
}
431+
432+
renderThread = new Thread(() -> {
433+
System.out.println("Thread started with id " + this.hashCode());
434+
435+
keepRunning = true;
436+
while (keepRunning) {
437+
isIdle = false;
438+
synchronized (pingPong) {
439+
Canvas c = pingPong.getCanvas();
440+
renderOnCanvas(c);
441+
pingPong.swap();
442+
}
443+
synchronized (renderSync) {
444+
postInvalidate();
445+
// prevent this thread from becoming an orphan
446+
// after the view is destroyed
447+
if (keepRunning) {
448+
try {
449+
renderSync.wait();
450+
} catch (InterruptedException e) {
451+
keepRunning = false;
434452
}
435453
}
436-
pingPong.recycle();
437454
}
438-
}, "Androidplot renderThread");
439-
}
455+
}
456+
System.out.println("Thread exited with id " + this.hashCode());
457+
renderThread = null;
458+
pingPong.recycle();
459+
}, "Androidplot renderThread");
440460
}
441461

442462
/**
@@ -745,11 +765,12 @@ public void redraw() {
745765
// only enter synchronized block if the call is expected to block OR
746766
// if the render thread is idle, so we know that we won't have to wait to
747767
// obtain a lock.
748-
if (isIdle) {
768+
if (renderThread != null && isIdle) {
749769
synchronized (renderSync) {
750770
renderSync.notify();
751771
}
752772
}
773+
753774
} else if(renderMode == RenderMode.USE_MAIN_THREAD) {
754775

755776
// are we on the UI thread?
@@ -778,6 +799,17 @@ protected void onDetachedFromWindow() {
778799
}
779800
}
780801

802+
@Override
803+
protected void onAttachedToWindow() {
804+
super.onAttachedToWindow();
805+
806+
// necessary to support rendering in recyclerview etc.
807+
if(renderMode == RenderMode.USE_BACKGROUND_THREAD && renderThread == null) {
808+
pingPong.resizeToLast();
809+
startBackgroundRendering();
810+
renderThread.start();
811+
}
812+
}
781813

782814
@Override
783815
protected synchronized void onSizeChanged (int w, int h, int oldw, int oldh) {

demoapp/build.gradle

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
*/
1616

1717
buildscript {
18-
18+
ext.kotlin_version = '1.5.31'
1919
repositories {
2020
mavenCentral()
2121
}
2222
dependencies {
2323
classpath 'com.github.triplet.gradle:play-publisher:3.6.0'
24+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
2425
}
2526
}
2627

@@ -29,9 +30,14 @@ plugins {
2930
id 'com.github.triplet.play' version '3.6.0'
3031
}
3132

33+
apply plugin: 'kotlin-android'
34+
3235
dependencies {
36+
implementation "androidx.core:core-ktx:1.6.0"
37+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
3338
implementation project(':androidplot-core')
3439
implementation 'com.crittercism:crittercism-android-agent:5.4.0'
40+
implementation 'androidx.recyclerview:recyclerview:1.2.1'
3541

3642
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
3743

@@ -43,6 +49,10 @@ dependencies {
4349
android {
4450
compileSdkVersion theCompileSdkVersion
4551

52+
buildFeatures {
53+
viewBinding true
54+
}
55+
4656
defaultConfig {
4757
versionCode theVersionCode
4858
versionName theVersionName
@@ -82,3 +92,6 @@ play {
8292
serviceAccountCredentials.set(file(System.getenv("PUBLISHER_ACCT_JSON_FILE") ?: "publisher.json"))
8393
track = 'beta'
8494
}
95+
repositories {
96+
mavenCentral()
97+
}

demoapp/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
</intent-filter>
9696
</activity>
9797
<activity android:name=".ListViewActivity" android:label="ListView Example"/>
98+
<activity android:name=".RecyclerViewActivity" android:label="RecyclerView Example"/>
9899
<activity android:name=".XYRegionExampleActivity" android:label="XYRegion Example">
99100
<intent-filter>
100101
<category android:name="android.intent.category.LAUNCHER" />

demoapp/src/main/java/com/androidplot/demos/MainActivity.java

Lines changed: 0 additions & 193 deletions
This file was deleted.

0 commit comments

Comments
 (0)