Highlight text shown in display asynchronously

This commit is contained in:
serso 2017-08-02 15:25:01 +02:00
parent da98947dab
commit 3bc913ac81
2 changed files with 74 additions and 20 deletions

View File

@ -133,6 +133,7 @@ public class Display {
if (this.view != view) { if (this.view != view) {
return; return;
} }
this.view.onDestroy();
this.view = null; this.view = null;
} }

View File

@ -22,30 +22,74 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import static android.util.TypedValue.COMPLEX_UNIT_SP;
import static android.util.TypedValue.applyDimension;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.AsyncTask;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.util.AttributeSet; import android.util.AttributeSet;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.views.AutoResizeTextView; import org.solovyev.android.views.AutoResizeTextView;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import static android.util.TypedValue.COMPLEX_UNIT_SP;
import static android.util.TypedValue.applyDimension;
public class DisplayView extends AutoResizeTextView { public class DisplayView extends AutoResizeTextView {
private class AsyncHighlighter extends AsyncTask<Void, Void, CharSequence> {
@NonNull
private final String text;
@Nullable
private final TextHighlighter highlighter;
AsyncHighlighter(@NonNull String text) {
this.text = text;
this.highlighter = getTextHighlighter();
}
boolean shouldAsync() {
return !TextUtils.isEmpty(text) && highlighter != null;
}
@NonNull
@Override
protected CharSequence doInBackground(Void... params) {
if (highlighter == null) {
return text;
}
try {
return highlighter.process(text).getCharSequence();
} catch (ParseException e) {
return text;
}
}
@Override
protected void onPostExecute(@NonNull CharSequence text) {
if (highlighterTask != this) {
return;
}
setText(text);
setTextColor(getTextColor().normal);
highlighterTask = null;
}
}
@Nullable @Nullable
private Engine engine; private Engine engine;
@Nullable @Nullable
private TextHighlighter textHighlighter; private TextHighlighter textHighlighter;
@Nonnull @Nonnull
private DisplayState state = DisplayState.empty(); private DisplayState state = DisplayState.empty();
@Nullable
private AsyncHighlighter highlighterTask;
public DisplayView(Context context) { public DisplayView(Context context) {
super(context); super(context);
@ -95,32 +139,41 @@ public class DisplayView extends AutoResizeTextView {
state = newState; state = newState;
if (state.valid) { if (state.valid) {
setText(highlightText(state)); asyncHighlightText(newState);
setTextColor(getTextColor().normal);
} else { } else {
cancelAsyncHighlightText(false);
setText(App.unspan(getText())); setText(App.unspan(getText()));
setTextColor(getTextColor().error); setTextColor(getTextColor().error);
} }
} }
private void cancelAsyncHighlightText(boolean applyLastState) {
if (highlighterTask == null) {
return;
}
highlighterTask.cancel(false);
if (applyLastState) {
highlighterTask.onPostExecute(highlighterTask.text);
}
highlighterTask = null;
}
private void asyncHighlightText(@NonNull DisplayState state) {
cancelAsyncHighlightText(false);
highlighterTask = new AsyncHighlighter(state.text);
if (highlighterTask.shouldAsync()) {
highlighterTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return;
}
highlighterTask.onPostExecute(state.text);
Check.isNull(highlighterTask);
}
public void setEngine(@Nullable Engine engine) { public void setEngine(@Nullable Engine engine) {
this.engine = engine; this.engine = engine;
} }
@NonNull public void onDestroy() {
private CharSequence highlightText(@Nonnull DisplayState state) { cancelAsyncHighlightText(true);
final String text = state.text;
if (TextUtils.isEmpty(text)) {
return "";
}
final TextHighlighter textHighlighter = getTextHighlighter();
if (textHighlighter == null) {
return text;
}
try {
return textHighlighter.process(text).getCharSequence();
} catch (ParseException e) {
return text;
}
} }
} }