api: floaty
This commit is contained in:
@@ -4,6 +4,8 @@ var window = floaty.window(
|
|||||||
</frame>
|
</frame>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
window.exitOnClose();
|
||||||
|
|
||||||
window.text.click(()=>{
|
window.text.click(()=>{
|
||||||
window.setAdjustEnabled(!window.isAdjustEnabled());
|
window.setAdjustEnabled(!window.isAdjustEnabled());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ var window = floaty.window(
|
|||||||
</frame>
|
</frame>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
window.exitOnClose();
|
||||||
|
|
||||||
window.text.click(()=>{
|
window.text.click(()=>{
|
||||||
window.setAdjustEnabled(!window.isAdjustEnabled());
|
window.setAdjustEnabled(!window.isAdjustEnabled());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ var window = floaty.window(
|
|||||||
</frame>
|
</frame>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
window.exitOnClose();
|
||||||
|
|
||||||
var execution = null;
|
var execution = null;
|
||||||
|
|
||||||
window.action.click(()=>{
|
window.action.click(()=>{
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ var window = floaty.window(
|
|||||||
</frame>
|
</frame>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setInterval(()=>{}, 1000);
|
||||||
|
|
||||||
var execution = null;
|
var execution = null;
|
||||||
|
|
||||||
//记录按键被按下时的触摸坐标
|
//记录按键被按下时的触摸坐标
|
||||||
@@ -33,7 +35,7 @@ window.action.setOnTouchListener(function(view, event){
|
|||||||
windowY + (event.getRawY() - y));
|
windowY + (event.getRawY() - y));
|
||||||
//如果按下的时间超过1.5秒判断为长按,退出脚本
|
//如果按下的时间超过1.5秒判断为长按,退出脚本
|
||||||
if(new Date().getTime() - downTime > 1500){
|
if(new Date().getTime() - downTime > 1500){
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case event.ACTION_UP:
|
case event.ACTION_UP:
|
||||||
@@ -58,5 +60,4 @@ function onClick(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(()=>{}, 1000);
|
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,15 @@ module.exports = function(__runtime__, scope){
|
|||||||
}
|
}
|
||||||
view.longClick = function(listener){
|
view.longClick = function(listener){
|
||||||
if(listener){
|
if(listener){
|
||||||
view.setOnLongClickListener(new android.view.View.OnLongClickListener(listener));
|
view.setOnLongClickListener(new android.view.View.OnLongClickListener(function(view){
|
||||||
|
try{
|
||||||
|
var r = listener(view);
|
||||||
|
return !!r;
|
||||||
|
}catch(e){
|
||||||
|
console.error(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}));
|
||||||
}else{
|
}else{
|
||||||
view.performLongClick();
|
view.performLongClick();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,8 +179,6 @@ public class ScriptEngineService {
|
|||||||
int n = stopAll();
|
int n = stopAll();
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
mUiHandler.toast(String.format(mContext.getString(R.string.text_already_stop_n_scripts), n));
|
mUiHandler.toast(String.format(mContext.getString(R.string.text_already_stop_n_scripts), n));
|
||||||
else
|
|
||||||
mUiHandler.toast(mContext.getString(R.string.text_no_running_script));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ScriptEngine> getEngines() {
|
public Set<ScriptEngine> getEngines() {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.stardust.autojs.R;
|
import com.stardust.autojs.R;
|
||||||
|
import com.stardust.concurrent.ConcurrentArrayList;
|
||||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
||||||
import com.stardust.util.SparseArrayEntries;
|
import com.stardust.util.SparseArrayEntries;
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/5/2.
|
* Created by Stardust on 2017/5/2.
|
||||||
*
|
* <p>
|
||||||
* TODO: 优化为无锁形式
|
* TODO: 优化为无锁形式
|
||||||
*/
|
*/
|
||||||
public class ConsoleView extends FrameLayout implements StardustConsole.LogListener {
|
public class ConsoleView extends FrameLayout implements StardustConsole.LogListener {
|
||||||
@@ -153,7 +154,7 @@ public class ConsoleView extends FrameLayout implements StardustConsole.LogListe
|
|||||||
return;
|
return;
|
||||||
int oldSize = mLogs.size();
|
int oldSize = mLogs.size();
|
||||||
ArrayList<StardustConsole.Log> logs = mConsole.getAllLogs();
|
ArrayList<StardustConsole.Log> logs = mConsole.getAllLogs();
|
||||||
synchronized (logs) {
|
synchronized (mConsole.getAllLogs()) {
|
||||||
final int size = logs.size();
|
final int size = logs.size();
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.stardust.autojs.core.console;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Looper;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
@@ -11,6 +10,7 @@ import com.stardust.autojs.annotation.ScriptInterface;
|
|||||||
import com.stardust.autojs.runtime.api.AbstractConsole;
|
import com.stardust.autojs.runtime.api.AbstractConsole;
|
||||||
import com.stardust.autojs.runtime.api.Console;
|
import com.stardust.autojs.runtime.api.Console;
|
||||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||||
|
import com.stardust.concurrent.ConcurrentArrayList;
|
||||||
import com.stardust.enhancedfloaty.FloatyService;
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
|
||||||
import com.stardust.util.UiHandler;
|
import com.stardust.util.UiHandler;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class FloatyWindow extends ResizableFloatyWindow {
|
|||||||
private boolean mCreated = false;
|
private boolean mCreated = false;
|
||||||
private View mMoveCursor;
|
private View mMoveCursor;
|
||||||
private View mResizer;
|
private View mResizer;
|
||||||
|
private View mCloseButton;
|
||||||
private MyFloaty mFloaty;
|
private MyFloaty mFloaty;
|
||||||
|
|
||||||
|
|
||||||
@@ -59,15 +60,22 @@ public class FloatyWindow extends ResizableFloatyWindow {
|
|||||||
View root = (View) mView.getParent().getParent();
|
View root = (View) mView.getParent().getParent();
|
||||||
mMoveCursor = root.findViewById(R.id.move_cursor);
|
mMoveCursor = root.findViewById(R.id.move_cursor);
|
||||||
mResizer = root.findViewById(R.id.resizer);
|
mResizer = root.findViewById(R.id.resizer);
|
||||||
|
mCloseButton = root.findViewById(R.id.close);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnCloseButtonClickListener(View.OnClickListener listener){
|
||||||
|
mCloseButton.setOnClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAdjustEnabled(boolean enabled) {
|
public void setAdjustEnabled(boolean enabled) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
mMoveCursor.setVisibility(View.GONE);
|
mMoveCursor.setVisibility(View.GONE);
|
||||||
mResizer.setVisibility(View.GONE);
|
mResizer.setVisibility(View.GONE);
|
||||||
|
mCloseButton.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
mMoveCursor.setVisibility(View.VISIBLE);
|
mMoveCursor.setVisibility(View.VISIBLE);
|
||||||
mResizer.setVisibility(View.VISIBLE);
|
mResizer.setVisibility(View.VISIBLE);
|
||||||
|
mCloseButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.stardust.autojs.core.inputevent;
|
package com.stardust.autojs.core.inputevent;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.stardust.pio.UncheckedIOException;
|
|||||||
import org.mozilla.javascript.Callable;
|
import org.mozilla.javascript.Callable;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
import org.mozilla.javascript.ContextFactory;
|
import org.mozilla.javascript.ContextFactory;
|
||||||
|
import org.mozilla.javascript.ErrorReporter;
|
||||||
import org.mozilla.javascript.ImporterTopLevel;
|
import org.mozilla.javascript.ImporterTopLevel;
|
||||||
import org.mozilla.javascript.Scriptable;
|
import org.mozilla.javascript.Scriptable;
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ public class ScriptRuntime {
|
|||||||
engines = new Engines(builder.mEngineService);
|
engines = new Engines(builder.mEngineService);
|
||||||
dialogs = new Dialogs(app, uiHandler, bridges);
|
dialogs = new Dialogs(app, uiHandler, bridges);
|
||||||
device = new Device(uiHandler.getContext());
|
device = new Device(uiHandler.getContext());
|
||||||
floaty = new Floaty(uiHandler, ui);
|
floaty = new Floaty(uiHandler, ui, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -295,7 +295,9 @@ public class ScriptRuntime {
|
|||||||
|
|
||||||
public void exit() {
|
public void exit() {
|
||||||
mThread.interrupt();
|
mThread.interrupt();
|
||||||
throw new ScriptInterruptedException();
|
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||||
|
throw new ScriptInterruptedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
@@ -10,22 +10,15 @@ import com.stardust.autojs.R;
|
|||||||
import com.stardust.autojs.core.floaty.FloatyWindow;
|
import com.stardust.autojs.core.floaty.FloatyWindow;
|
||||||
import com.stardust.autojs.core.ui.JsLayoutInflater;
|
import com.stardust.autojs.core.ui.JsLayoutInflater;
|
||||||
import com.stardust.autojs.core.ui.JsViewHelper;
|
import com.stardust.autojs.core.ui.JsViewHelper;
|
||||||
import com.stardust.autojs.rhino.ProxyObject;
|
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||||
import com.stardust.concurrent.VolatileDispose;
|
import com.stardust.concurrent.VolatileDispose;
|
||||||
import com.stardust.enhancedfloaty.FloatyService;
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
import com.stardust.util.UiHandler;
|
import com.stardust.util.UiHandler;
|
||||||
import com.stardust.util.ViewUtil;
|
import com.stardust.util.ViewUtil;
|
||||||
|
|
||||||
import org.mozilla.javascript.NativeJavaObject;
|
|
||||||
import org.mozilla.javascript.Scriptable;
|
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
|
||||||
import org.mozilla.javascript.UniqueTag;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,9 +31,11 @@ public class Floaty {
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private UiHandler mUiHandler;
|
private UiHandler mUiHandler;
|
||||||
private Set<JsFloatyWindow> mWindows = new HashSet<>();
|
private Set<JsFloatyWindow> mWindows = new HashSet<>();
|
||||||
|
private ScriptRuntime mRuntime;
|
||||||
|
|
||||||
public Floaty(UiHandler uiHandler, UI ui) {
|
public Floaty(UiHandler uiHandler, UI ui, ScriptRuntime runtime) {
|
||||||
mUiHandler = uiHandler;
|
mUiHandler = uiHandler;
|
||||||
|
mRuntime = runtime;
|
||||||
mContext = new ContextThemeWrapper(mUiHandler.getContext(), R.style.AppTheme);
|
mContext = new ContextThemeWrapper(mUiHandler.getContext(), R.style.AppTheme);
|
||||||
mJsLayoutInflater = ui.getJsLayoutInflater();
|
mJsLayoutInflater = ui.getJsLayoutInflater();
|
||||||
}
|
}
|
||||||
@@ -69,20 +64,16 @@ public class Floaty {
|
|||||||
Iterator<JsFloatyWindow> iterator = mWindows.iterator();
|
Iterator<JsFloatyWindow> iterator = mWindows.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
JsFloatyWindow window = iterator.next();
|
JsFloatyWindow window = iterator.next();
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
window.close();
|
||||||
window.mWindow.close();
|
|
||||||
} else {
|
|
||||||
mUiHandler.post(() -> window.mWindow.close());
|
|
||||||
}
|
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class JsFloatyWindow {
|
public class JsFloatyWindow {
|
||||||
|
|
||||||
private Map<String, View> mViewCache = new HashMap<>();
|
|
||||||
private View mView;
|
private View mView;
|
||||||
private FloatyWindow mWindow;
|
private FloatyWindow mWindow;
|
||||||
|
private boolean mExitOnClose = false;
|
||||||
|
|
||||||
public JsFloatyWindow(View view) {
|
public JsFloatyWindow(View view) {
|
||||||
mWindow = new FloatyWindow(view);
|
mWindow = new FloatyWindow(view);
|
||||||
@@ -91,6 +82,7 @@ public class Floaty {
|
|||||||
FloatyService.addWindow(mWindow);
|
FloatyService.addWindow(mWindow);
|
||||||
});
|
});
|
||||||
mWindow.waitFor();
|
mWindow.waitFor();
|
||||||
|
mWindow.setOnCloseButtonClickListener(v -> close());
|
||||||
//setSize(mWindow.getWindowBridge().getScreenWidth() / 2, mWindow.getWindowBridge().getScreenHeight() / 2);
|
//setSize(mWindow.getWindowBridge().getScreenWidth() / 2, mWindow.getWindowBridge().getScreenHeight() / 2);
|
||||||
mView = view;
|
mView = view;
|
||||||
}
|
}
|
||||||
@@ -108,17 +100,17 @@ public class Floaty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
return mWindow.getWindowBridge().getWidth();
|
return mWindow.getRootView().getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight() {
|
public int getHeight() {
|
||||||
return mWindow.getWindowBridge().getHeight();
|
return mWindow.getRootView().getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSize(int w, int h) {
|
public void setSize(int w, int h) {
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
ViewUtil.setViewMeasure(mWindow.getRootView(), w, h);
|
ViewUtil.setViewMeasure(mWindow.getRootView(), w, h);
|
||||||
// mWindow.getWindowBridge().updateMeasure(w, h);
|
// mWindow.getWindowBridge().updateMeasure(w, h);
|
||||||
} else {
|
} else {
|
||||||
mUiHandler.post(() -> {
|
mUiHandler.post(() -> {
|
||||||
ViewUtil.setViewMeasure(mWindow.getRootView(), w, h);
|
ViewUtil.setViewMeasure(mWindow.getRootView(), w, h);
|
||||||
@@ -147,6 +139,10 @@ public class Floaty {
|
|||||||
return mWindow.isAdjustEnabled();
|
return mWindow.isAdjustEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void exitOnClose() {
|
||||||
|
mExitOnClose = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
if (!mWindows.remove(this)) {
|
if (!mWindows.remove(this)) {
|
||||||
return;
|
return;
|
||||||
@@ -156,6 +152,9 @@ public class Floaty {
|
|||||||
} else {
|
} else {
|
||||||
mUiHandler.post(() -> mWindow.close());
|
mUiHandler.post(() -> mWindow.close());
|
||||||
}
|
}
|
||||||
|
if (mExitOnClose) {
|
||||||
|
mRuntime.exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,55 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="wrap_content"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_height="wrap_content">
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_margin="12dp">
|
android:layout_margin="12dp">
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/resizer"
|
android:id="@+id/resizer"
|
||||||
android:layout_width="25dp"
|
android:layout_width="25dp"
|
||||||
android:layout_height="25dp"
|
android:layout_height="25dp"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_gravity="bottom|right"
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:background="@drawable/circle_cool_black"
|
android:background="@drawable/circle_cool_black"
|
||||||
android:padding="6dp"
|
android:padding="6dp"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:src="@drawable/ic_resizer"
|
android:src="@drawable/ic_resizer"
|
||||||
android:tint="@android:color/white"
|
android:tint="@android:color/white"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/close"
|
||||||
|
android:layout_width="25dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_gravity="top|right"
|
||||||
|
android:background="@drawable/circle_cool_black"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/ic_close_white_24dp"
|
||||||
|
android:tint="@android:color/white"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/move_cursor"
|
android:id="@+id/move_cursor"
|
||||||
android:layout_width="25dp"
|
android:layout_width="25dp"
|
||||||
android:layout_height="25dp"
|
android:layout_height="25dp"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_gravity="top|left"
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:background="@drawable/circle_cool_black"
|
android:background="@drawable/circle_cool_black"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:src="@drawable/ic_move_cursor"
|
android:src="@drawable/ic_move_cursor"
|
||||||
android:tint="@android:color/white"
|
android:tint="@android:color/white"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</FrameLayout>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.stardust.concurrent;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/12/30.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ConcurrentArrayList<T> {
|
||||||
|
|
||||||
|
private final Class<T> mTClass;
|
||||||
|
private volatile T[] mArray;
|
||||||
|
private final AtomicInteger mSize = new AtomicInteger();
|
||||||
|
private final Object mArrayResizeLock = mSize;
|
||||||
|
|
||||||
|
public ConcurrentArrayList(Class<T> tClass) {
|
||||||
|
mTClass = tClass;
|
||||||
|
mArray = newArray(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(T element) {
|
||||||
|
int index = mSize.getAndIncrement();
|
||||||
|
ensureCapacity(index);
|
||||||
|
mArray[index] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T get(int i) {
|
||||||
|
int size = mSize.get();
|
||||||
|
if (i >= size) {
|
||||||
|
throw new IndexOutOfBoundsException("i = " + i + ", size = " + size);
|
||||||
|
}
|
||||||
|
return mArray[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return mSize.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getArrayResizeLock() {
|
||||||
|
return mArrayResizeLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private T[] newArray(int size) {
|
||||||
|
return (T[]) Array.newInstance(mTClass, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureCapacity(int index) {
|
||||||
|
if (index < mArray.length)
|
||||||
|
return;
|
||||||
|
synchronized (mArrayResizeLock) {
|
||||||
|
if (index < mArray.length)
|
||||||
|
return;
|
||||||
|
T[] newArray = newArray(mArray.length * 2);
|
||||||
|
System.arraycopy(mArray, 0, newArray, 0, mArray.length);
|
||||||
|
mArray = newArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user