selfKits) {
+
+ }
+
+ public static void show() {
+
+ }
+
+ public static void hide() {
+ }
+
+ public static boolean isShow() {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/Category.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/Category.java
new file mode 100644
index 000000000..35cae9068
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/Category.java
@@ -0,0 +1,17 @@
+package com.didichuxing.doraemonkit.kit;
+
+/**
+ * Created by zhangweida on 2018/6/22.
+ */
+
+public interface Category {
+ int BIZ = 0;
+
+ int TOOLS = 1;
+
+ int PERFORMANCE = 2;
+
+ int UI = 3;
+
+ int CLOSE = 5;
+}
\ No newline at end of file
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/IKit.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/IKit.java
new file mode 100644
index 000000000..20e1d3001
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/IKit.java
@@ -0,0 +1,19 @@
+package com.didichuxing.doraemonkit.kit;
+
+import android.content.Context;
+
+/**
+ * Created by zhangweida on 2018/6/22.
+ */
+
+public interface IKit {
+ int getCategory();
+
+ int getName();
+
+ int getIcon();
+
+ void onClick(Context context);
+
+ void onAppInit(Context context);
+}
\ No newline at end of file
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java
new file mode 100644
index 000000000..f87189a95
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java
@@ -0,0 +1,277 @@
+package com.didichuxing.doraemonkit.kit.network.common;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+
+/**
+ * The header fields of a single HTTP message. Values are uninterpreted strings; use {@code Request}
+ * and {@code Response} for interpreted headers. This class maintains the order of the header fields
+ * within the HTTP message.
+ *
+ * This class tracks header values line-by-line. A field with multiple comma- separated values on
+ * the same line will be treated as a field with a single value by this class. It is the caller's
+ * responsibility to detect and split on commas if their field permits multiple values. This
+ * simplifies use of single-valued fields whose values routinely contain commas, such as cookies or
+ * dates.
+ *
+ *
This class trims whitespace from values. It never returns values with leading or trailing
+ * whitespace.
+ *
+ *
Instances of this class are immutable. Use {@link Builder} to create instances.
+ */
+public final class CommonHeaders {
+
+ CommonHeaders(Builder builder) {
+ }
+
+ private CommonHeaders(String[] namesAndValues) {
+ }
+
+ /** Returns the last value corresponding to the specified field, or null. */
+ public String get(String name) {
+ return null;
+ }
+
+ /**
+ * Returns the last value corresponding to the specified field parsed as an HTTP date, or null if
+ * either the field is absent or cannot be parsed as a date.
+ */
+ public Date getDate(String name) {
+ return null;
+ }
+
+ /** Returns the number of field values. */
+ public int size() {
+ return 0;
+ }
+
+ /** Returns the field at {@code position}. */
+ public String name(int index) {
+ return null;
+ }
+
+ /** Returns the value at {@code index}. */
+ public String value(int index) {
+ return null;
+ }
+
+ /** Returns an immutable case-insensitive set of header names. */
+ public Set names() {
+ return null;
+ }
+
+ /** Returns an immutable list of the header values for {@code name}. */
+ public List values(String name) {
+ return null;
+ }
+
+ public Builder newBuilder() {
+ Builder result = new Builder();
+ return result;
+ }
+
+ /**
+ * Returns true if {@code other} is a {@code Headers} object with the same headers, with the same
+ * casing, in the same order. Note that two headers instances may be semantically equal
+ * but not equal according to this method. In particular, none of the following sets of headers
+ * are equal according to this method: {@code
+ *
+ * 1. Original
+ * Content-Type: text/html
+ * Content-Length: 50
+ *
+ * 2. Different order
+ * Content-Length: 50
+ * Content-Type: text/html
+ *
+ * 3. Different case
+ * content-type: text/html
+ * content-length: 50
+ *
+ * 4. Different values
+ * Content-Type: text/html
+ * Content-Length: 050
+ * }
+ *
+ * Applications that require semantically equal headers should convert them into a canonical form
+ * before comparing them for equality.
+ */
+ @Override public boolean equals(Object other) {
+ return false;
+ }
+
+ @Override public int hashCode() {
+ return 0;
+ }
+
+ @Override public String toString() {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0, size = size(); i < size; i++) {
+ result.append(name(i)).append(": ").append(value(i)).append("\n");
+ }
+ return result.toString();
+ }
+
+ public Map> toMultimap() {
+ Map> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ for (int i = 0, size = size(); i < size; i++) {
+ String name = name(i).toLowerCase(Locale.US);
+ List values = result.get(name);
+ if (values == null) {
+ values = new ArrayList<>(2);
+ result.put(name, values);
+ }
+ values.add(value(i));
+ }
+ return result;
+ }
+
+ private static String get(String[] namesAndValues, String name) {
+ for (int i = namesAndValues.length - 2; i >= 0; i -= 2) {
+ if (name.equalsIgnoreCase(namesAndValues[i])) {
+ return namesAndValues[i + 1];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns headers for the alternating header names and values. There must be an even number of
+ * arguments, and they must alternate between header names and values.
+ */
+ public static CommonHeaders of(String... namesAndValues) {
+ if (namesAndValues == null) throw new NullPointerException("namesAndValues == null");
+ if (namesAndValues.length % 2 != 0) {
+ throw new IllegalArgumentException("Expected alternating header names and values");
+ }
+
+ // Make a defensive copy and clean it up.
+ namesAndValues = namesAndValues.clone();
+ for (int i = 0; i < namesAndValues.length; i++) {
+ if (namesAndValues[i] == null) throw new IllegalArgumentException("Headers cannot be null");
+ namesAndValues[i] = namesAndValues[i].trim();
+ }
+
+ // Check for malformed headers.
+ for (int i = 0; i < namesAndValues.length; i += 2) {
+ String name = namesAndValues[i];
+ String value = namesAndValues[i + 1];
+ if (name.length() == 0 || name.indexOf('\0') != -1 || value.indexOf('\0') != -1) {
+ throw new IllegalArgumentException("Unexpected header: " + name + ": " + value);
+ }
+ }
+
+ return new CommonHeaders(namesAndValues);
+ }
+
+ /**
+ * Returns headers for the header names and values in the {@link Map}.
+ */
+ public static CommonHeaders of(Map headers) {
+ if (headers == null) throw new NullPointerException("headers == null");
+
+ // Make a defensive copy and clean it up.
+ String[] namesAndValues = new String[headers.size() * 2];
+ int i = 0;
+ for (Map.Entry header : headers.entrySet()) {
+ if (header.getKey() == null || header.getValue() == null) {
+ throw new IllegalArgumentException("Headers cannot be null");
+ }
+ String name = header.getKey().trim();
+ String value = header.getValue().trim();
+ if (name.length() == 0 || name.indexOf('\0') != -1 || value.indexOf('\0') != -1) {
+ throw new IllegalArgumentException("Unexpected header: " + name + ": " + value);
+ }
+ namesAndValues[i] = name;
+ namesAndValues[i + 1] = value;
+ i += 2;
+ }
+
+ return new CommonHeaders(namesAndValues);
+ }
+
+ public static final class Builder {
+ final List namesAndValues = new ArrayList<>(20);
+
+ /**
+ * Add a header line without any validation. Only appropriate for headers from the remote peer
+ * or cache.
+ */
+ Builder addLenient(String line) {
+ int index = line.indexOf(":", 1);
+ if (index != -1) {
+ return addLenient(line.substring(0, index), line.substring(index + 1));
+ } else if (line.startsWith(":")) {
+ // Work around empty header names and header names that start with a
+ // colon (created by old broken SPDY versions of the response cache).
+ return addLenient("", line.substring(1)); // Empty header name.
+ } else {
+ return addLenient("", line); // No header name.
+ }
+ }
+
+ /** Add an header line containing a field name, a literal colon, and a value. */
+ public Builder add(String line) {
+ int index = line.indexOf(":");
+ if (index == -1) {
+ throw new IllegalArgumentException("Unexpected header: " + line);
+ }
+ return add(line.substring(0, index).trim(), line.substring(index + 1));
+ }
+
+ /** Add a field with the specified value. */
+ public Builder add(String name, String value) {
+ return addLenient(name, value);
+ }
+
+ /**
+ * Add a field with the specified value without any validation. Only appropriate for headers
+ * from the remote peer or cache.
+ */
+ Builder addLenient(String name, String value) {
+ namesAndValues.add(name);
+ namesAndValues.add(value.trim());
+ return this;
+ }
+
+ public Builder removeAll(String name) {
+ for (int i = 0; i < namesAndValues.size(); i += 2) {
+ if (name.equalsIgnoreCase(namesAndValues.get(i))) {
+ namesAndValues.remove(i); // name
+ namesAndValues.remove(i); // value
+ i -= 2;
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Set a field with the specified value. If the field is not found, it is added. If the field is
+ * found, the existing values are replaced.
+ */
+ public Builder set(String name, String value) {
+ return this;
+ }
+
+
+ /** Equivalent to {@code build().get(name)}, but potentially faster. */
+ public String get(String name) {
+ for (int i = namesAndValues.size() - 2; i >= 0; i -= 2) {
+ if (name.equalsIgnoreCase(namesAndValues.get(i))) {
+ return namesAndValues.get(i + 1);
+ }
+ }
+ return null;
+ }
+
+ public CommonHeaders build() {
+ return new CommonHeaders(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonInspectorRequest.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonInspectorRequest.java
new file mode 100644
index 000000000..596b6c411
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonInspectorRequest.java
@@ -0,0 +1,90 @@
+package com.didichuxing.doraemonkit.kit.network.common;
+
+import android.text.TextUtils;
+
+import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
+
+import java.util.List;
+
+/**
+ * @desc: 抓包通用请求bean
+ */
+public class CommonInspectorRequest implements NetworkInterpreter.InspectorRequest {
+ private final int mRequestId;
+ private final String url;
+ private final String method;
+ private final String body;
+ private final CommonHeaders headers;
+
+ public CommonInspectorRequest(
+ int requestId,
+ String url,
+ String method,
+ String body,
+ CommonHeaders headers) {
+ mRequestId = requestId;
+ this.url = url;
+ this.method = method;
+ this.body = body;
+ this.headers = headers;
+ }
+
+ @Override
+ public int id() {
+ return mRequestId;
+ }
+
+
+ @Override
+ public String url() {
+ return url;
+ }
+
+ @Override
+ public String method() {
+ return method;
+ }
+
+ @Override
+ public byte[] body() {
+ if (TextUtils.isEmpty(body)) {
+ return null;
+ }
+ return body.getBytes();
+ }
+
+ @Override
+ public int headerCount() {
+ if (headers != null) {
+ return headers.size();
+ }
+ return 0;
+ }
+
+ @Override
+ public String headerName(int index) {
+ if (headers != null) {
+ return headers.name(index);
+ }
+ return null;
+ }
+
+ @Override
+ public String headerValue(int index) {
+ if (headers != null) {
+ return headers.value(index);
+ }
+ return null;
+ }
+
+ @Override
+ public String firstHeaderValue(String name) {
+ if (headers != null) {
+ List values = headers.values(name);
+ if (values != null && values.size() > 0) {
+ return values.get(0);
+ }
+ }
+ return null;
+ }
+}
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonInspectorResponse.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonInspectorResponse.java
new file mode 100644
index 000000000..0ce76ad69
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonInspectorResponse.java
@@ -0,0 +1,74 @@
+package com.didichuxing.doraemonkit.kit.network.common;
+
+import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
+
+import java.util.List;
+
+public class CommonInspectorResponse implements NetworkInterpreter.InspectorResponse {
+ private final int mRequestId;
+ private final String url;
+ private final int statusCode;
+ private final CommonHeaders headers;
+
+ public CommonInspectorResponse(
+ int requestId,
+ String url,
+ int statusCode,
+ CommonHeaders headers) {
+ mRequestId = requestId;
+ this.url = url;
+ this.statusCode = statusCode;
+ this.headers = headers;
+ }
+
+ @Override
+ public int requestId() {
+ return mRequestId;
+ }
+
+ @Override
+ public String url() {
+ return url;
+ }
+
+ @Override
+ public int statusCode() {
+ return statusCode;
+ }
+
+ @Override
+ public int headerCount() {
+ if (headers != null) {
+ return headers.size();
+ }
+ return 0;
+ }
+
+ @Override
+ public String headerName(int index) {
+ if (headers != null) {
+ return headers.name(index);
+ }
+ return null;
+ }
+
+ @Override
+ public String headerValue(int index) {
+ if (headers != null) {
+ return headers.value(index);
+ }
+ return null;
+ }
+
+ @Override
+ public String firstHeaderValue(String name) {
+ if (headers != null) {
+ List values = headers.values(name);
+ if (values != null && values.size() > 0) {
+ return values.get(0);
+ }
+ }
+ return null;
+ }
+}
+
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/NetworkPrinterHelper.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/NetworkPrinterHelper.java
new file mode 100644
index 000000000..6a7a89ea1
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/common/NetworkPrinterHelper.java
@@ -0,0 +1,38 @@
+package com.didichuxing.doraemonkit.kit.network.common;
+
+/**
+ * @desc: 目前DoraemonKit只支持okhttp3和HttpUrlConnection的自动抓包,其他网络库如果想把网络请求打印出来,需要手动调用该类的方法将请求内容写入
+ */
+public class NetworkPrinterHelper {
+ private static final String TAG = "NetworkLogHelper";
+
+ private NetworkPrinterHelper() {
+
+ }
+
+
+ private static class Holder {
+ private static NetworkPrinterHelper INSTANCE = new NetworkPrinterHelper();
+ }
+
+ private static NetworkPrinterHelper get() {
+ return Holder.INSTANCE;
+ }
+
+ /**
+ * @return 返回一个请求id,后续所有的更新操作都需要传入这个请求id,用以定位对应的bean
+ */
+ public static int obtainRequestId() {
+ return 0;
+ }
+
+ public static void updateRequest( CommonInspectorRequest request) {
+ }
+
+ public static void updateResponse( CommonInspectorResponse response) {
+ }
+
+ public static void updateResponseBody(int requestId, String body) {
+ }
+
+}
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java
new file mode 100644
index 000000000..780c068ff
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java
@@ -0,0 +1,67 @@
+package com.didichuxing.doraemonkit.kit.network.core;
+
+import java.io.IOException;
+
+/**
+ * @desc: 网络请求解析类
+ */
+public class NetworkInterpreter {
+
+ /**
+ * Represents the request that will be sent over HTTP. Note that for many implementations
+ * of HTTP the request constructed may differ from the request actually sent over the wire.
+ * For instance, additional headers like {@code Host}, {@code User-Agent}, {@code Content-Type},
+ * etc may not be part of this request but should be injected if necessary. Some stacks offer
+ * inspection of the raw request about to be sent to the server which is preferable.
+ */
+ public interface InspectorRequest extends InspectorRequestCommon {
+
+ String url();
+
+ /**
+ * HTTP method ("GET", "POST", "DELETE", etc).
+ */
+ String method();
+
+ /**
+ * Provide the body if part of an entity-enclosing request (like "POST" or "PUT"). May
+ * return null otherwise.
+ */
+ byte[] body() throws IOException;
+ }
+
+ public interface InspectorResponse extends InspectorResponseCommon {
+ String url();
+ }
+
+
+ public interface InspectorRequestCommon extends InspectorHeaders {
+ /**
+ * Unique identifier for this request. This identifier must be used in all other network
+ * events corresponding to this request. Identifiers may be re-used for HTTP requests or
+ * WebSockets that have exhuasted the state machine to its final closed/finished state.
+ */
+ int id();
+
+ }
+
+ public interface InspectorResponseCommon extends InspectorHeaders {
+ /**
+ * @see InspectorRequest#id()
+ */
+ int requestId();
+
+ int statusCode();
+
+ }
+
+ public interface InspectorHeaders {
+ int headerCount();
+
+ String headerName(int index);
+
+ String headerValue(int index);
+
+ String firstHeaderValue(String name);
+ }
+}
diff --git a/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java
new file mode 100644
index 000000000..e8516eb9c
--- /dev/null
+++ b/Android/doraemonkit-no-op/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java
@@ -0,0 +1,13 @@
+package com.didichuxing.doraemonkit.kit.webdoor;
+
+import android.content.Context;
+
+/**
+ * Created by wanglikun on 2018/10/10.
+ */
+
+public class WebDoorManager {
+ public interface WebDoorCallback {
+ void overrideUrlLoading(Context context, String url);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit-no-op/upload.gradle b/Android/doraemonkit-no-op/upload.gradle
new file mode 100644
index 000000000..e928c4a80
--- /dev/null
+++ b/Android/doraemonkit-no-op/upload.gradle
@@ -0,0 +1,15 @@
+apply plugin: 'com.novoda.bintray-release'
+// 配置发布
+publish {
+ def groupProjectID = 'com.didichuxing.doraemonkit'
+ def artifactProjectID = 'doraemonkit-no-op'
+ def publishVersionID = '1.1.3'
+
+ userOrg = 'doraemonkit'
+ repoName = 'DoraemonKit'
+ groupId = groupProjectID
+ artifactId = artifactProjectID
+ publishVersion = publishVersionID
+ desc = '{library description}'
+ website = '{github_url}'
+}
\ No newline at end of file
diff --git a/Android/doraemonkit-no-op/upload.sh b/Android/doraemonkit-no-op/upload.sh
new file mode 100644
index 000000000..d220f4318
--- /dev/null
+++ b/Android/doraemonkit-no-op/upload.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+echo -n "please enter bintray userid ->"
+read userid_bintray
+echo -n "please enter bintray apikey ->"
+read apikey_bintray
+../gradlew clean build bintrayUpload -PbintrayUser=${userid_bintray} -PbintrayKey=${apikey_bintray} -PdryRun=false
\ No newline at end of file
diff --git a/Android/doraemonkit/build.gradle b/Android/doraemonkit/build.gradle
index d93691116..800473694 100644
--- a/Android/doraemonkit/build.gradle
+++ b/Android/doraemonkit/build.gradle
@@ -26,17 +26,21 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation 'com.didichuxing.doraemonkit:adb:1.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:appcompat-v7:26.1.0'
- implementation 'com.android.support:recyclerview-v7:26.1.0'
+ implementation ('com.android.support:recyclerview-v7:26.1.0'){
+ exclude group: 'com.android.support'
+ }
+
implementation('com.scottyab:rootbeer-lib:0.0.6') {
+ transitive=true
exclude group: 'com.android.support'
}
implementation 'com.squareup.okhttp3:okhttp:3.6.0'
compileOnly 'com.squareup.okio:okio:1.11.0'
- compileOnly 'com.didichuxing.doraemonkit:compiler:1.0.0'
+ compileOnly 'com.didichuxing.doraemonkit:compiler:1.0.1'
testImplementation 'junit:junit:4.12'
+
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
diff --git a/Android/doraemonkit/src/main/AndroidManifest.xml b/Android/doraemonkit/src/main/AndroidManifest.xml
index 9dc266bf4..2f222eb1a 100644
--- a/Android/doraemonkit/src/main/AndroidManifest.xml
+++ b/Android/doraemonkit/src/main/AndroidManifest.xml
@@ -2,36 +2,20 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-->
-
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonHooker.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonHooker.java
new file mode 100644
index 000000000..202504150
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonHooker.java
@@ -0,0 +1,51 @@
+package com.didichuxing.doraemonkit;
+
+import android.app.Application;
+
+import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterManager;
+import com.didichuxing.doraemonkit.util.LogHelper;
+
+import org.aspectj.lang.NoAspectBoundException;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+
+/**
+ * 通用的hooker
+ */
+@Aspect
+public class DoraemonHooker {
+ public static final String TAG = "DoraemonHooker";
+ private static /* synthetic */ Throwable ajc$initFailureCause;
+ public static /* synthetic */ DoraemonHooker ajc$perSingletonInstance = null;
+
+ static {
+ try {
+ ajc$perSingletonInstance = new DoraemonHooker();
+ } catch (Throwable th) {
+ ajc$initFailureCause = th;
+ }
+ }
+
+ public static DoraemonHooker aspectOf() {
+ if (ajc$perSingletonInstance != null) {
+ return ajc$perSingletonInstance;
+ }
+ throw new NoAspectBoundException("com.didichuxing.doraemonkit.DoraemonHooker", ajc$initFailureCause);
+ }
+
+ public static boolean hasAspect() {
+ return ajc$perSingletonInstance != null;
+ }
+
+ @Around("execution(* android.app.Application.onCreate(..))")
+ public void install(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+ LogHelper.d(TAG, "hook application.onCreate start");
+ TimeCounterManager.get().onAppCreateStart();
+ proceedingJoinPoint.proceed();
+ Application app = (Application) proceedingJoinPoint.getTarget();
+ DoraemonKit.install(app);
+ TimeCounterManager.get().onAppCreateEnd();
+ LogHelper.d(TAG, "hook application.onCreate end");
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java
index a544cfdc8..21611594c 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java
@@ -13,22 +13,25 @@
import com.didichuxing.doraemonkit.kit.alignruler.AlignRuler;
import com.didichuxing.doraemonkit.kit.blockmonitor.BlockMonitorKit;
import com.didichuxing.doraemonkit.kit.colorpick.ColorPicker;
-import com.didichuxing.doraemonkit.kit.cpu.Cpu;
+import com.didichuxing.doraemonkit.kit.parameter.cpu.Cpu;
import com.didichuxing.doraemonkit.kit.crash.Crash;
import com.didichuxing.doraemonkit.kit.dataclean.DataClean;
import com.didichuxing.doraemonkit.kit.fileexplorer.FileExplorer;
-import com.didichuxing.doraemonkit.kit.frameInfo.FrameInfo;
+import com.didichuxing.doraemonkit.kit.parameter.frameInfo.FrameInfo;
import com.didichuxing.doraemonkit.kit.gpsmock.GpsHookManager;
import com.didichuxing.doraemonkit.kit.gpsmock.GpsMock;
+import com.didichuxing.doraemonkit.kit.layoutborder.LayoutBorder;
import com.didichuxing.doraemonkit.kit.logInfo.LogInfo;
import com.didichuxing.doraemonkit.kit.network.NetworkKit;
-import com.didichuxing.doraemonkit.kit.ram.Ram;
+import com.didichuxing.doraemonkit.kit.parameter.ram.Ram;
import com.didichuxing.doraemonkit.kit.sysinfo.SysInfo;
import com.didichuxing.doraemonkit.kit.temporaryclose.TemporaryClose;
+import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterKit;
import com.didichuxing.doraemonkit.kit.viewcheck.ViewChecker;
import com.didichuxing.doraemonkit.kit.webdoor.WebDoor;
import com.didichuxing.doraemonkit.kit.webdoor.WebDoorManager;
import com.didichuxing.doraemonkit.ui.FloatIconPage;
+import com.didichuxing.doraemonkit.ui.KitFloatPage;
import com.didichuxing.doraemonkit.ui.UniversalActivity;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
import com.didichuxing.doraemonkit.ui.base.PageIntent;
@@ -36,6 +39,7 @@
import com.didichuxing.doraemonkit.util.DoraemonStatisticsUtil;
import com.didichuxing.doraemonkit.util.PermissionUtil;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -46,19 +50,47 @@
public class DoraemonKit {
private static final String TAG = "DoraemonKit";
- private static final SparseArray> mKitMap = new SparseArray<>();
+ private static SparseArray> sKitMap = new SparseArray<>();
+
+ private static List sListeners = new ArrayList<>();
private static boolean sHasRequestPermission;
- public static void setWebDoorCallback(WebDoorManager.WebDoorCallback callback) {
- WebDoorManager.getInstance().setWebDoorCallback(callback);
- }
+ private static boolean sHasInit = false;
+
+ private static WeakReference sCurrentResumedActivity;
+
+ private static boolean sShowFloatingIcon = true;
public static void install(final Application app) {
install(app, null);
}
+ public static void setWebDoorCallback(WebDoorManager.WebDoorCallback callback) {
+ WebDoorManager.getInstance().setWebDoorCallback(callback);
+ if (WebDoorManager.getInstance().isWebDoorEnable()) {
+ List tools = sKitMap.get(Category.TOOLS);
+ if (tools != null) {
+ tools.add(new WebDoor());
+ }
+ }
+ }
+
public static void install(final Application app, List selfKits) {
+ if (sHasInit) {
+ if (selfKits != null) {
+ List biz = sKitMap.get(Category.BIZ);
+ if (biz != null) {
+ biz.clear();
+ biz.addAll(selfKits);
+ for (IKit kit : biz) {
+ kit.onAppInit(app);
+ }
+ }
+ }
+ return;
+ }
+ sHasInit = true;
GpsHookManager.getInstance().init();
app.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
int startedActivityCounts;
@@ -78,17 +110,25 @@ public void onActivityStarted(Activity activity) {
@Override
public void onActivityResumed(Activity activity) {
- FloatPageManager.getInstance().onActivityResumed(activity);
if (PermissionUtil.canDrawOverlays(activity)) {
- showFloatIcon(activity);
+ if (sShowFloatingIcon) {
+ showFloatIcon(activity);
+ }
} else {
requestPermission(activity);
}
+ for (ActivityLifecycleListener listener : sListeners) {
+ listener.onActivityResumed(activity);
+ }
+ sCurrentResumedActivity = new WeakReference<>(activity);
}
@Override
public void onActivityPaused(Activity activity) {
- FloatPageManager.getInstance().onActivityPaused(activity);
+ for (ActivityLifecycleListener listener : sListeners) {
+ listener.onActivityPaused(activity);
+ }
+ sCurrentResumedActivity = null;
}
@Override
@@ -109,7 +149,7 @@ public void onActivityDestroyed(Activity activity) {
}
});
- mKitMap.clear();
+ sKitMap.clear();
List tool = new ArrayList<>();
List biz = new ArrayList<>();
List ui = new ArrayList<>();
@@ -121,7 +161,9 @@ public void onActivityDestroyed(Activity activity) {
if (GpsHookManager.getInstance().isMockEnable()) {
tool.add(new GpsMock());
}
- tool.add(new WebDoor());
+ if (WebDoorManager.getInstance().isWebDoorEnable()) {
+ tool.add(new WebDoor());
+ }
tool.add(new Crash());
tool.add(new LogInfo());
tool.add(new DataClean());
@@ -131,6 +173,7 @@ public void onActivityDestroyed(Activity activity) {
performance.add(new Ram());
performance.add(new NetworkKit());
performance.add(new BlockMonitorKit());
+ performance.add(new TimeCounterKit());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ui.add(new ColorPicker());
@@ -138,6 +181,7 @@ public void onActivityDestroyed(Activity activity) {
ui.add(new AlignRuler());
ui.add(new ViewChecker());
+ ui.add(new LayoutBorder());
exit.add(new TemporaryClose());
@@ -158,11 +202,11 @@ public void onActivityDestroyed(Activity activity) {
kit.onAppInit(app);
}
- mKitMap.put(Category.BIZ, biz);
- mKitMap.put(Category.PERFORMANCE, performance);
- mKitMap.put(Category.TOOLS, tool);
- mKitMap.put(Category.UI, ui);
- mKitMap.put(Category.CLOSE, exit);
+ sKitMap.put(Category.BIZ, biz);
+ sKitMap.put(Category.PERFORMANCE, performance);
+ sKitMap.put(Category.TOOLS, tool);
+ sKitMap.put(Category.UI, ui);
+ sKitMap.put(Category.CLOSE, exit);
FloatPageManager.getInstance().init(app);
@@ -187,17 +231,17 @@ private static void showFloatIcon(Context context) {
}
public static List getKitList(int catgory) {
- if (mKitMap.get(catgory) != null) {
- return new ArrayList<>(mKitMap.get(catgory));
+ if (sKitMap.get(catgory) != null) {
+ return new ArrayList<>(sKitMap.get(catgory));
} else {
return null;
}
}
public static List getKitItems(int catgory) {
- if (mKitMap.get(catgory) != null) {
+ if (sKitMap.get(catgory) != null) {
List kitItems = new ArrayList<>();
- for (IKit kit : mKitMap.get(catgory)) {
+ for (IKit kit : sKitMap.get(catgory)) {
kitItems.add(new KitItem(kit));
}
return kitItems;
@@ -205,4 +249,42 @@ public static List getKitItems(int catgory) {
return null;
}
}
+
+ public interface ActivityLifecycleListener {
+ void onActivityResumed(Activity activity);
+
+ void onActivityPaused(Activity activity);
+ }
+
+ public static void registerListener(ActivityLifecycleListener listener) {
+ sListeners.add(listener);
+ }
+
+ public static void unRegisterListener(ActivityLifecycleListener listener) {
+ sListeners.remove(listener);
+ }
+
+ public static void show() {
+ if (!isShow()) {
+ showFloatIcon(null);
+ }
+ sShowFloatingIcon = true;
+
+ }
+
+ public static void hide() {
+ FloatPageManager.getInstance().removeAll(KitFloatPage.class);
+// sShowFloatingIcon = false;
+ }
+
+ public static boolean isShow() {
+ return sShowFloatingIcon;
+ }
+
+ public static Activity getCurrentResumedActivity() {
+ if (sCurrentResumedActivity != null && sCurrentResumedActivity.get() != null) {
+ return sCurrentResumedActivity.get();
+ }
+ return null;
+ }
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/AlignRulerConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/AlignRulerConfig.java
new file mode 100644
index 000000000..30813551b
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/AlignRulerConfig.java
@@ -0,0 +1,19 @@
+package com.didichuxing.doraemonkit.config;
+
+import android.content.Context;
+
+import com.didichuxing.doraemonkit.constant.SharedPrefsKey;
+import com.didichuxing.doraemonkit.util.SharedPrefsUtil;
+
+/**
+ * @author wanglikun
+ */
+public class AlignRulerConfig {
+ public static boolean isAlignRulerOpen(Context context) {
+ return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.ALIGN_RULER_OPEN, false);
+ }
+
+ public static void setAlignRulerOpen(Context context, boolean open) {
+ SharedPrefsUtil.putBoolean(context, SharedPrefsKey.ALIGN_RULER_OPEN, open);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/ColorPickConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/ColorPickConfig.java
new file mode 100644
index 000000000..1d96de3c5
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/ColorPickConfig.java
@@ -0,0 +1,19 @@
+package com.didichuxing.doraemonkit.config;
+
+import android.content.Context;
+
+import com.didichuxing.doraemonkit.constant.SharedPrefsKey;
+import com.didichuxing.doraemonkit.util.SharedPrefsUtil;
+
+/**
+ * @author wanglikun
+ */
+public class ColorPickConfig {
+ public static boolean isColorPickOpen(Context context) {
+ return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.COLOR_PICK_OPEN, false);
+ }
+
+ public static void setColorPickOpen(Context context, boolean open) {
+ SharedPrefsUtil.putBoolean(context, SharedPrefsKey.COLOR_PICK_OPEN, open);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/GpsMockConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/GpsMockConfig.java
index cf6247d6c..9e4fa614a 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/GpsMockConfig.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/GpsMockConfig.java
@@ -10,14 +10,6 @@
*/
public class GpsMockConfig {
- public static boolean isGPSOpen(Context context) {
- return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.GPS_OPEN, false);
- }
-
- public static void setGPSOpen(Context context, boolean open) {
- SharedPrefsUtil.putBoolean(context, SharedPrefsKey.GPS_OPEN, open);
- }
-
public static boolean isGPSMockOpen(Context context) {
return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.GPS_MOCK_OPEN, false);
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/LayoutBorderConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/LayoutBorderConfig.java
new file mode 100644
index 000000000..734d6626d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/LayoutBorderConfig.java
@@ -0,0 +1,25 @@
+package com.didichuxing.doraemonkit.config;
+
+/**
+ * Created by wanglikun on 2019/1/7
+ */
+public class LayoutBorderConfig {
+ private static boolean sLayoutBorderOpen;
+ private static boolean sLayoutLevelOpen;
+
+ public static boolean isLayoutBorderOpen() {
+ return sLayoutBorderOpen;
+ }
+
+ public static void setLayoutBorderOpen(boolean open) {
+ sLayoutBorderOpen = open;
+ }
+
+ public static boolean isLayoutLevelOpen() {
+ return sLayoutLevelOpen;
+ }
+
+ public static void setLayoutLevelOpen(boolean open) {
+ sLayoutLevelOpen = open;
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/LogInfoConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/LogInfoConfig.java
new file mode 100644
index 000000000..dc6187a83
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/LogInfoConfig.java
@@ -0,0 +1,19 @@
+package com.didichuxing.doraemonkit.config;
+
+import android.content.Context;
+
+import com.didichuxing.doraemonkit.constant.SharedPrefsKey;
+import com.didichuxing.doraemonkit.util.SharedPrefsUtil;
+
+/**
+ * @author wanglikun
+ */
+public class LogInfoConfig {
+ public static boolean isLogInfoOpen(Context context) {
+ return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.LOG_INFO_OPEN, false);
+ }
+
+ public static void setLogInfoOpen(Context context, boolean open) {
+ SharedPrefsUtil.putBoolean(context, SharedPrefsKey.LOG_INFO_OPEN, open);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/ViewCheckConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/ViewCheckConfig.java
new file mode 100644
index 000000000..e7ab2a5aa
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/ViewCheckConfig.java
@@ -0,0 +1,19 @@
+package com.didichuxing.doraemonkit.config;
+
+import android.content.Context;
+
+import com.didichuxing.doraemonkit.constant.SharedPrefsKey;
+import com.didichuxing.doraemonkit.util.SharedPrefsUtil;
+
+/**
+ * Created by wanglikun on 2018/12/28
+ */
+public class ViewCheckConfig {
+ public static boolean isViewCheckOpen(Context context) {
+ return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.VIEW_CHECK_OPEN, false);
+ }
+
+ public static void setViewCheckOpen(Context context, boolean open) {
+ SharedPrefsUtil.putBoolean(context, SharedPrefsKey.VIEW_CHECK_OPEN, open);
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java
index a41fe6c54..b5aeb4c8e 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/FragmentIndex.java
@@ -20,4 +20,6 @@ public interface FragmentIndex {
int FRAGMENT_NETWORK_MONITOR = 13;
int FRAGMENT_CPU = 14;
int FRAGMENT_RAM = 15;
+ int FRAGMENT_LAYOUT_BORDER = 16;
+ int FRAGMENT_TIME_COUNTER= 17;
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/PageTag.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/PageTag.java
index bf79e584c..81e21903f 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/PageTag.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/PageTag.java
@@ -8,4 +8,5 @@ public interface PageTag {
String PAGE_ALIGN_RULER_MARKER = "page_align_ruler_marker";
String PAGE_VIEW_CHECK = "page_view_check";
String PAGE_COLOR_PICKER_INFO = "page_color_picker_info";
+ String PAGE_TIME_COUNTER = "page_time_counter";
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java
index cecd40781..7d323bc4b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java
@@ -6,13 +6,16 @@
public interface SharedPrefsKey {
String FRAME_INFO_FPS_OPEN = "frame_info_fps_open";
- String FRAME_INFO_SF_OPEN = "frame_info_sf_open";
String FRAME_INFO_CPU_OPEN = "frame_info_cpu_open";
String FRAME_INFO_MEMORY_OPEN = "frame_info_memory_open";
- String FRAME_INFO_TRAFFIC_OPEN = "frame_info_traffic_open";
- String GPS_OPEN = "gps_open";
String GPS_MOCK_OPEN = "gps_mock_open";
String CRASH_OPEN = "crash_open";
String FLOAT_ICON_POS_X = "float_icon_pos_x";
String FLOAT_ICON_POS_Y = "float_icon_pos_y";
+ String LOG_INFO_OPEN = "log_info_open";
+ String COLOR_PICK_OPEN = "color_pick_open";
+ String ALIGN_RULER_OPEN = "align_ruler_open";
+ String VIEW_CHECK_OPEN = "view_check_open";
+ String LAYOUT_BORDER_OPEN = "layout_border_open";
+ String LAYOUT_LEVEL_OPEN = "layout_level_open";
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRuler.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRuler.java
index ed304a9ed..7f6390a12 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRuler.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRuler.java
@@ -1,14 +1,14 @@
package com.didichuxing.doraemonkit.kit.alignruler;
import android.content.Context;
-import android.content.Intent;
import com.didichuxing.doraemonkit.R;
-import com.didichuxing.doraemonkit.constant.BundleKey;
-import com.didichuxing.doraemonkit.constant.FragmentIndex;
+import com.didichuxing.doraemonkit.config.AlignRulerConfig;
+import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.kit.Category;
import com.didichuxing.doraemonkit.kit.IKit;
-import com.didichuxing.doraemonkit.ui.UniversalActivity;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.PageIntent;
/**
* Created by wanglikun on 2018/9/19.
@@ -32,14 +32,24 @@ public int getIcon() {
@Override
public void onClick(Context context) {
- Intent intent = new Intent(context, UniversalActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(BundleKey.FRAGMENT_INDEX, FragmentIndex.FRAGMENT_ALIGN_RULER_SETTING);
- context.startActivity(intent);
+ PageIntent pageIntent = new PageIntent(AlignRulerMarkerFloatPage.class);
+ pageIntent.tag = PageTag.PAGE_ALIGN_RULER_MARKER;
+ pageIntent.mode=PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(pageIntent);
+
+ pageIntent=new PageIntent(AlignRulerLineFloatPage.class);
+ pageIntent.mode=PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(pageIntent);
+
+ pageIntent=new PageIntent(AlignRulerInfoFloatPage.class);
+ pageIntent.mode=PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(pageIntent);
+
+ AlignRulerConfig.setAlignRulerOpen(context, true);
}
@Override
- public void onAppInit(Context context) {
-
+ public void onAppInit(Context context) {
+ AlignRulerConfig.setAlignRulerOpen(context, false);
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerInfoFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerInfoFloatPage.java
index 6fb4f731e..da7f2a771 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerInfoFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerInfoFloatPage.java
@@ -2,29 +2,42 @@
import android.content.Context;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.AlignRulerConfig;
import com.didichuxing.doraemonkit.constant.PageTag;
-import com.didichuxing.doraemonkit.ui.alignruler.AlignInfoView;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
+import com.didichuxing.doraemonkit.util.UIUtils;
/**
- * Created by wanglikun on 2018/11/13.
+ * Created by wanglikun on 2018/12/3.
*/
-public class AlignRulerInfoFloatPage extends BaseFloatPage implements AlignRulerMarkerFloatPage.OnAlignRulerMarkerPositionChangeListener {
+public class AlignRulerInfoFloatPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener, AlignRulerMarkerFloatPage.OnAlignRulerMarkerPositionChangeListener {
+ private WindowManager mWindowManager;
+ private TextView mAlignHex;
+ private ImageView mClose;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
private AlignRulerMarkerFloatPage mMarker;
- private AlignInfoView mAlignInfoView;
+ private int mWindowWidth;
+ private int mWindowHeight;
@Override
protected void onCreate(Context context) {
super.onCreate(context);
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mMarker = (AlignRulerMarkerFloatPage) FloatPageManager.getInstance().getFloatPage(PageTag.PAGE_ALIGN_RULER_MARKER);
mMarker.addPositionChangeListener(this);
+ mWindowWidth = UIUtils.getWidthPixels(context);
+ mWindowHeight = UIUtils.getHeightPixels(context);
}
@Override
@@ -35,25 +48,69 @@ protected void onDestroy() {
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_align_ruler_info, view, false);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_align_ruler_info, null);
}
@Override
protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
- params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
- params.height = WindowManager.LayoutParams.MATCH_PARENT;
+ params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
+ params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ params.x = 0;
+ params.y = UIUtils.getHeightPixels(getContext()) - UIUtils.dp2px(getContext(), 85);
}
@Override
protected void onViewCreated(View view) {
super.onViewCreated(view);
- mAlignInfoView = findViewById(R.id.info_view);
+ initView();
+ }
+
+ private void initView() {
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
+ mAlignHex = findViewById(R.id.align_hex);
+ mClose = findViewById(R.id.close);
+ mClose.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlignRulerConfig.setAlignRulerOpen(getContext(), false);
+ FloatPageManager.getInstance().removeAll(AlignRulerMarkerFloatPage.class);
+ FloatPageManager.getInstance().removeAll(AlignRulerLineFloatPage.class);
+ FloatPageManager.getInstance().removeAll(AlignRulerInfoFloatPage.class);
+ }
+ });
+ }
+
+
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
}
@Override
public void onPositionChanged(int x, int y) {
- mAlignInfoView.showInfo(x, y);
+ int left = x;
+ int top = y;
+ int right = mWindowWidth - left;
+ int bottom = mWindowHeight - top;
+ mAlignHex.setText(getResources().getString(R.string.dk_align_info_text, left, right, top, bottom));
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerLineFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerLineFloatPage.java
new file mode 100644
index 000000000..979481303
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerLineFloatPage.java
@@ -0,0 +1,70 @@
+package com.didichuxing.doraemonkit.kit.alignruler;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.constant.PageTag;
+import com.didichuxing.doraemonkit.ui.alignruler.AlignLineView;
+import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+
+/**
+ * Created by wanglikun on 2018/11/13.
+ */
+
+public class AlignRulerLineFloatPage extends BaseFloatPage implements AlignRulerMarkerFloatPage.OnAlignRulerMarkerPositionChangeListener {
+ private AlignRulerMarkerFloatPage mMarker;
+ private AlignLineView mAlignInfoView;
+
+ @Override
+ protected void onCreate(Context context) {
+ super.onCreate(context);
+ mMarker = (AlignRulerMarkerFloatPage) FloatPageManager.getInstance().getFloatPage(PageTag.PAGE_ALIGN_RULER_MARKER);
+ mMarker.addPositionChangeListener(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mMarker.removePositionChangeListener(this);
+ }
+
+ @Override
+ protected View onCreateView(Context context, ViewGroup view) {
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_align_ruler_line, view, false);
+ }
+
+ @Override
+ protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
+ params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+ params.height = WindowManager.LayoutParams.MATCH_PARENT;
+ params.width = WindowManager.LayoutParams.MATCH_PARENT;
+ }
+
+ @Override
+ protected void onViewCreated(View view) {
+ super.onViewCreated(view);
+ mAlignInfoView = findViewById(R.id.info_view);
+ }
+
+ @Override
+ public void onPositionChanged(int x, int y) {
+ mAlignInfoView.showInfo(x, y);
+ }
+
+ @Override
+ public void onEnterForeground() {
+ super.onEnterForeground();
+ getRootView().setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onEnterBackground() {
+ super.onEnterBackground();
+ getRootView().setVisibility(View.GONE);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerMarkerFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerMarkerFloatPage.java
index ac4d3dcdf..3c807fb4e 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerMarkerFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerMarkerFloatPage.java
@@ -4,12 +4,12 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import com.didichuxing.doraemonkit.R;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
import com.didichuxing.doraemonkit.util.UIUtils;
import java.util.ArrayList;
@@ -19,17 +19,16 @@
* Created by wanglikun on 2018/9/20.
*/
-public class AlignRulerMarkerFloatPage extends BaseFloatPage implements View.OnTouchListener {
+public class AlignRulerMarkerFloatPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener {
private List mPositionChangeListeners = new ArrayList<>();
- private float sdX, sdY;
- private float ldX, ldY;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
private WindowManager mWindowManager;
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_align_ruler_marker, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_align_ruler_marker, null);
}
@Override
@@ -39,7 +38,12 @@ protected void onViewCreated(View view) {
}
private void initView() {
- getRootView().setOnTouchListener(this);
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
}
@Override
@@ -51,37 +55,6 @@ protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
params.y = UIUtils.getHeightPixels(getContext()) / 2;
}
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- float x = event.getRawX();
- float y = event.getRawY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- sdX = ldX = x;
- sdY = ldY = y;
- return false;
- case MotionEvent.ACTION_MOVE:
- getLayoutParams().x += (x - ldX + 0.5f);
- getLayoutParams().y += (y - ldY + 0.5f);
- ldX = x;
- ldY = y;
- mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
- for (OnAlignRulerMarkerPositionChangeListener listener : mPositionChangeListeners) {
- listener.onPositionChanged(getLayoutParams().x + getRootView().getWidth() / 2, getLayoutParams().y + getRootView().getHeight() / 2);
- }
- return false;
- case MotionEvent.ACTION_UP:
- int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (Math.abs(x - sdX) <= mTouchSlop && Math.abs(y - sdY) <= mTouchSlop) {
- return false;
- }
- return true;
- default:
- break;
- }
- return false;
- }
-
@Override
protected void onCreate(Context context) {
super.onCreate(context);
@@ -94,6 +67,26 @@ protected void onDestroy() {
removePositionChangeListeners();
}
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ for (OnAlignRulerMarkerPositionChangeListener listener : mPositionChangeListeners) {
+ listener.onPositionChanged(getLayoutParams().x + getRootView().getWidth() / 2, getLayoutParams().y + getRootView().getHeight() / 2);
+ }
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
+ }
+
public interface OnAlignRulerMarkerPositionChangeListener {
void onPositionChanged(int x, int y);
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerSettingFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerSettingFragment.java
index 123189d52..843e4dbbe 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerSettingFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/alignruler/AlignRulerSettingFragment.java
@@ -8,6 +8,7 @@
import android.view.View;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.AlignRulerConfig;
import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.ui.base.BaseFragment;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
@@ -42,7 +43,7 @@ public void onRightClick() {
mSettingList = findViewById(R.id.setting_list);
mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
mSettingItemAdapter = new SettingItemAdapter(getContext());
- mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_align_ruler, false));
+ mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_align_ruler, AlignRulerConfig.isAlignRulerOpen(getContext())));
mSettingList.setAdapter(mSettingItemAdapter);
mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
@Override
@@ -52,11 +53,12 @@ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
PageIntent pageIntent = new PageIntent(AlignRulerMarkerFloatPage.class);
pageIntent.tag = PageTag.PAGE_ALIGN_RULER_MARKER;
FloatPageManager.getInstance().add(pageIntent);
- FloatPageManager.getInstance().add(new PageIntent(AlignRulerInfoFloatPage.class));
+ FloatPageManager.getInstance().add(new PageIntent(AlignRulerLineFloatPage.class));
} else {
FloatPageManager.getInstance().removeAll(AlignRulerMarkerFloatPage.class);
- FloatPageManager.getInstance().removeAll(AlignRulerInfoFloatPage.class);
+ FloatPageManager.getInstance().removeAll(AlignRulerLineFloatPage.class);
}
+ AlignRulerConfig.setAlignRulerOpen(getContext(), on);
}
}
});
@@ -64,6 +66,6 @@ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_align_ruler_setting;
+ return R.layout.dk_fragment_align_ruler_setting;
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListAdapter.java
index cf6e611a3..32459c147 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListAdapter.java
@@ -30,7 +30,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_block_list, parent, false);
+ return inflater.inflate(R.layout.dk_item_block_list, parent, false);
}
private class ItemViewHolder extends AbsViewBinder {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListFragment.java
index 8499cbdb1..191eb14c8 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockListFragment.java
@@ -5,6 +5,7 @@
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.TextView;
@@ -35,7 +36,7 @@ public class BlockListFragment extends BaseFragment implements OnBlockInfoUpdate
@Override
protected int onRequestLayout() {
- return R.layout.fragment_block_list;
+ return R.layout.dk_fragment_block_list;
}
@Override
@@ -50,6 +51,8 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
private void initView() {
mBlockList = findViewById(R.id.block_list);
mLogDetail = findViewById(R.id.tx_block_detail);
+ mLogDetail.setMovementMethod(ScrollingMovementMethod.getInstance());
+
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
mBlockList.setLayoutManager(layoutManager);
mBlockListAdapter = new BlockListAdapter(getContext());
@@ -60,10 +63,10 @@ private void initView() {
mBlockListAdapter.setOnItemClickListener(new BlockListAdapter.OnItemClickListener() {
@Override
public void onClick(BlockInfo info) {
- mLogDetail.setText(info.toString());
+ mLogDetail.setText(info.toString() + info.toString() + info.toString());
mLogDetail.setVisibility(View.VISIBLE);
mBlockList.setVisibility(View.GONE);
- mTitleBar.setTitle(R.string.dk_kit_block_monitor_detail);
+ mTitleBar.setTitle(getResources().getString(R.string.dk_kit_block_monitor_detail), false);
}
});
mTitleBar = findViewById(R.id.title_bar);
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockMonitorFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockMonitorFragment.java
index 5367ca9db..7d13983d1 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockMonitorFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/BlockMonitorFragment.java
@@ -24,7 +24,7 @@ public class BlockMonitorFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_block_monitor_index;
+ return R.layout.dk_fragment_block_monitor_index;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/core/BlockMonitorManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/core/BlockMonitorManager.java
index 821ff7b45..f8202c8a7 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/core/BlockMonitorManager.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/blockmonitor/core/BlockMonitorManager.java
@@ -11,6 +11,7 @@
import com.didichuxing.doraemonkit.constant.FragmentIndex;
import com.didichuxing.doraemonkit.kit.blockmonitor.BlockMonitorFragment;
import com.didichuxing.doraemonkit.kit.blockmonitor.bean.BlockInfo;
+import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterManager;
import com.didichuxing.doraemonkit.ui.UniversalActivity;
import com.didichuxing.doraemonkit.util.LogHelper;
import com.didichuxing.doraemonkit.util.NotificationUtils;
@@ -53,6 +54,8 @@ public void start(Context context) {
LogHelper.e(TAG, "start fail, context is null");
return;
}
+ // 卡顿检测和跳转耗时统计都使用了Printer的方式,无法同时工作
+ TimeCounterManager.get().stop();
mContext = context.getApplicationContext();
if (mMonitorCore == null) {
mMonitorCore = new MonitorCore();
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickConstants.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickConstants.java
new file mode 100644
index 000000000..b89d80802
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickConstants.java
@@ -0,0 +1,8 @@
+package com.didichuxing.doraemonkit.kit.colorpick;
+
+public class ColorPickConstants {
+ public static final int PIX_INTERVAL = 16;
+ public static final int PICK_AREA_SIZE = PIX_INTERVAL * 2;
+ public static final int PICK_VIEW_SIZE = PICK_AREA_SIZE * PIX_INTERVAL;
+ public static final String TEXT_FOCUS_INFO="%s %d,%d";
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPicker.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPicker.java
index 96ddf8946..59eb2b636 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPicker.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPicker.java
@@ -4,11 +4,12 @@
import android.content.Intent;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.ColorPickConfig;
import com.didichuxing.doraemonkit.constant.BundleKey;
import com.didichuxing.doraemonkit.constant.FragmentIndex;
import com.didichuxing.doraemonkit.kit.Category;
import com.didichuxing.doraemonkit.kit.IKit;
-import com.didichuxing.doraemonkit.ui.UniversalActivity;
+import com.didichuxing.doraemonkit.ui.TranslucentActivity;
/**
* Created by wanglikun on 2018/9/13.
@@ -34,7 +35,7 @@ public int getIcon() {
@Override
public void onClick(Context context) {
- Intent intent = new Intent(context, UniversalActivity.class);
+ Intent intent = new Intent(context, TranslucentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(BundleKey.FRAGMENT_INDEX, FragmentIndex.FRAGMENT_COLOR_PICKER_SETTING);
context.startActivity(intent);
@@ -42,6 +43,6 @@ public void onClick(Context context) {
@Override
public void onAppInit(Context context) {
-
+ ColorPickConfig.setColorPickOpen(context, false);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerFloatPage.java
index 7f4cc8d9c..21c88fc74 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerFloatPage.java
@@ -2,14 +2,11 @@
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.PixelFormat;
import android.os.Build;
import android.support.annotation.RequiresApi;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -17,11 +14,13 @@
import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
import com.didichuxing.doraemonkit.ui.colorpicker.ColorPickerView;
+import com.didichuxing.doraemonkit.util.ImageUtil;
import com.didichuxing.doraemonkit.util.UIUtils;
/**
- * Created by wanglikun on 2018/9/13.
+ * Cr eated by wanglikun on 2018/9/13.
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@@ -32,9 +31,10 @@ public class ColorPickerFloatPage extends BaseFloatPage implements View.OnTouchL
private ImageCapture mImageCapture;
private ColorPickerView mPickerView;
private ColorPickerInfoFloatPage mInfoFloatPage;
-
- private float sdX, sdY;
- private float ldX, ldY;
+ private TouchProxy mTouchProxy;
+ private int width;
+ private int height;
+ private int statuBarHeight;
@Override
protected void onViewCreated(View view) {
@@ -43,106 +43,111 @@ protected void onViewCreated(View view) {
private void initView() {
mPickerView = findViewById(R.id.picker_view);
+ ViewGroup.LayoutParams params = mPickerView.getLayoutParams();
+ //大小必须是2的倍数
+ params.width = ColorPickConstants.PICK_VIEW_SIZE;
+ params.height = ColorPickConstants.PICK_VIEW_SIZE;
+ mPickerView.setLayoutParams(params);
getRootView().setOnTouchListener(this);
+
+ width = UIUtils.getWidthPixels(getContext());
+ height = UIUtils.getHeightPixels(getContext());
+ statuBarHeight = UIUtils.getStatusBarHeight(getContext());
+ captureInfo(500);
}
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_color_picker, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_color_picker, null);
}
@Override
protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
- params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
}
@Override
protected void onCreate(Context context) {
+ mTouchProxy = new TouchProxy(new TouchProxy.OnTouchEventListener() {
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ WindowManager.LayoutParams params = getLayoutParams();
+ params.x += dx;
+ params.y += dy;
+ checkBound(params);
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ showInfo();
+ }
+
+ private void checkBound(WindowManager.LayoutParams layoutParams) {
+ if (layoutParams.x < -mPickerView.getWidth() / 2) {
+ layoutParams.x = -mPickerView.getWidth() / 2;
+ }
+ if (layoutParams.x > width - mPickerView.getWidth() / 2 - ColorPickConstants.PIX_INTERVAL) {
+ layoutParams.x = width - mPickerView.getWidth() / 2 - ColorPickConstants.PIX_INTERVAL;
+ }
+ if (layoutParams.y < -mPickerView.getHeight() / 2 - statuBarHeight) {
+ layoutParams.y = -mPickerView.getHeight() / 2 - statuBarHeight;
+ }
+ if (layoutParams.y > height - mPickerView.getHeight() / 2 - ColorPickConstants.PIX_INTERVAL) {
+ layoutParams.y = height - mPickerView.getHeight() / 2 - ColorPickConstants.PIX_INTERVAL;
+ }
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+ captureInfo(100);
+ }
+ });
mInfoFloatPage = (ColorPickerInfoFloatPage) FloatPageManager.getInstance().getFloatPage(PageTag.PAGE_COLOR_PICKER_INFO);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mImageCapture = new ImageCapture();
mImageCapture.init(context, getBundle());
}
- private void checkLayoutParams() {
- if (getLayoutParams().x < 0) {
- getLayoutParams().x = 0;
- } else if (getLayoutParams().x > UIUtils.getWidthPixels(getContext())) {
- getLayoutParams().x = UIUtils.getWidthPixels(getContext());
- }
- if (getLayoutParams().y < 0) {
- getLayoutParams().y = 0;
- } else if (getLayoutParams().y > UIUtils.getRealHeightPixels(getContext())) {
- getLayoutParams().y = UIUtils.getRealHeightPixels(getContext());
- }
- }
-
@Override
protected void onDestroy() {
mImageCapture.destroy();
}
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- float x = event.getRawX();
- float y = event.getRawY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- captureInfo();
- showInfo(getLayoutParams().x + getRootView().getWidth() / 2, getLayoutParams().y + getRootView().getHeight() / 2);
- sdX = ldX = x;
- sdY = ldY = y;
- return false;
- case MotionEvent.ACTION_MOVE:
- getLayoutParams().x += (x - ldX + 0.5f);
- getLayoutParams().y += (y - ldY + 0.5f);
- ldX = x;
- ldY = y;
- checkLayoutParams();
- showInfo(x, y);
- mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
- return false;
- case MotionEvent.ACTION_UP:
- int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (Math.abs(x - sdX) <= mTouchSlop && Math.abs(y - sdY) <= mTouchSlop) {
- return false;
- }
- return true;
- default:
- break;
- }
- return false;
- }
-
- private void showInfo(float x, float y) {
- if (mImageCapture.getBitmap() == null) {
- return;
- }
- float posX = x - getResources().getDimensionPixelSize(R.dimen.dk_dp_6);
- float posY = y - getResources().getDimensionPixelSize(R.dimen.dk_dp_6);
- int width = UIUtils.dp2px(getContext(), getResources().getDimensionPixelSize(R.dimen.dk_dp_6));
- int height = UIUtils.dp2px(getContext(), getResources().getDimensionPixelSize(R.dimen.dk_dp_6));
- if (width + posX > mImageCapture.getBitmap().getWidth() || height + posY > mImageCapture.getBitmap().getHeight() || posX < 0 || posY < 0) {
+ private void showInfo() {
+ int x = getLayoutParams().x;
+ int y = getLayoutParams().y;
+ int pickAreaSize = ColorPickConstants.PICK_AREA_SIZE;
+ int startX = x + ColorPickConstants.PICK_VIEW_SIZE / 2 - pickAreaSize / 2;
+ int startY = y + ColorPickConstants.PICK_VIEW_SIZE / 2 - pickAreaSize / 2 + UIUtils.getStatusBarHeight(getContext());
+ Bitmap bitmap = mImageCapture.getPartBitmap(startX, startY, pickAreaSize, pickAreaSize);
+ if (bitmap == null) {
return;
}
- Bitmap bitmap = Bitmap.createBitmap(mImageCapture.getBitmap(), (int) posX, (int) posY, width, height);
- mPickerView.setBitmap(bitmap);
int xCenter = bitmap.getWidth() / 2;
int yCenter = bitmap.getHeight() / 2;
- int colorInt = bitmap.getPixel(xCenter, yCenter);
- mInfoFloatPage.showInfo(colorInt);
+ int colorInt = ImageUtil.getPixel(bitmap, xCenter, yCenter);
+ mPickerView.setBitmap(bitmap, colorInt, startX, startY);
+ mInfoFloatPage.showInfo(colorInt, startX, startY);
}
- private void captureInfo() {
+ private void captureInfo(int delay) {
getRootView().setVisibility(View.GONE);
- postDelayed(new Runnable() {
+ getRootView().postDelayed(new Runnable() {
@Override
public void run() {
mImageCapture.capture();
getRootView().setVisibility(View.VISIBLE);
+ showInfo();
}
- }, 100);
+ }, delay);
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerInfoFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerInfoFloatPage.java
index 7ede50f23..b65f6db22 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerInfoFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerInfoFloatPage.java
@@ -6,15 +6,16 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.ColorPickConfig;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
import com.didichuxing.doraemonkit.util.ColorUtil;
import com.didichuxing.doraemonkit.util.UIUtils;
@@ -22,15 +23,12 @@
* Created by wanglikun on 2018/12/3.
*/
-public class ColorPickerInfoFloatPage extends BaseFloatPage implements View.OnTouchListener {
-
- private float sdX, sdY;
- private float ldX, ldY;
-
+public class ColorPickerInfoFloatPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener {
private WindowManager mWindowManager;
private ImageView mColor;
private TextView mColorHex;
private ImageView mClose;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
@Override
protected void onCreate(Context context) {
@@ -40,7 +38,7 @@ protected void onCreate(Context context) {
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_color_picker_info, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_color_picker_info, null);
}
@Override
@@ -59,49 +57,44 @@ protected void onViewCreated(View view) {
}
private void initView() {
- getRootView().setOnTouchListener(this);
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
mColor = findViewById(R.id.color);
mColorHex = findViewById(R.id.color_hex);
mClose = findViewById(R.id.close);
mClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ ColorPickConfig.setColorPickOpen(getContext(), false);
FloatPageManager.getInstance().removeAll(ColorPickerFloatPage.class);
FloatPageManager.getInstance().removeAll(ColorPickerInfoFloatPage.class);
}
});
}
+ public void showInfo(@ColorInt int colorInt, int x, int y) {
+ mColor.setImageDrawable(new ColorDrawable(colorInt));
+ mColorHex.setText(String.format(ColorPickConstants.TEXT_FOCUS_INFO, ColorUtil.parseColorInt(colorInt), x + ColorPickConstants.PIX_INTERVAL, y + ColorPickConstants.PIX_INTERVAL));
+ }
+
@Override
- public boolean onTouch(View v, MotionEvent event) {
- float x = event.getRawX();
- float y = event.getRawY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- sdX = ldX = x;
- sdY = ldY = y;
- return false;
- case MotionEvent.ACTION_MOVE:
- getLayoutParams().x += (x - ldX + 0.5f);
- getLayoutParams().y += (y - ldY + 0.5f);
- ldX = x;
- ldY = y;
- mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
- return false;
- case MotionEvent.ACTION_UP:
- int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (Math.abs(x - sdX) <= mTouchSlop && Math.abs(y - sdY) <= mTouchSlop) {
- return false;
- }
- return true;
- default:
- break;
- }
- return false;
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
}
- public void showInfo(@ColorInt int colorInt) {
- mColor.setImageDrawable(new ColorDrawable(colorInt));
- mColorHex.setText(ColorUtil.parseColorInt(colorInt));
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerSettingFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerSettingFragment.java
index 2fe08462b..b2ec42dbd 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerSettingFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ColorPickerSettingFragment.java
@@ -7,67 +7,28 @@
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.ColorPickConfig;
import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.constant.RequestCode;
import com.didichuxing.doraemonkit.ui.base.BaseFragment;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
import com.didichuxing.doraemonkit.ui.base.PageIntent;
-import com.didichuxing.doraemonkit.ui.setting.SettingItem;
-import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
-import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
/**
* Created by wanglikun on 2018/9/15.
*/
public class ColorPickerSettingFragment extends BaseFragment {
- private HomeTitleBar mTitleBar;
- private SettingItem mSettingItem;
- private RecyclerView mSettingList;
- private SettingItemAdapter mSettingItemAdapter;
+
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- initTitleBar();
- }
-
- private void initTitleBar() {
- mTitleBar = findViewById(R.id.title_bar);
- mTitleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() {
- @Override
- public void onRightClick() {
- finish();
- }
- });
- mSettingItem = new SettingItem(R.string.dk_kit_color_picker, false);
- mSettingList = findViewById(R.id.setting_list);
- mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
- mSettingItemAdapter = new SettingItemAdapter(getContext());
- mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
- @Override
- public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
- if (mSettingItem == data) {
- if (on) {
- boolean result = requestCaptureScreen();
- if (!result) {
- mSettingItem.isChecked = true;
- mSettingItemAdapter.notifyDataSetChanged();
- }
- } else {
- FloatPageManager.getInstance().removeAll(ColorPickerFloatPage.class);
- FloatPageManager.getInstance().removeAll(ColorPickerInfoFloatPage.class);
- }
- }
- }
- });
- mSettingItemAdapter.append(mSettingItem);
- mSettingList.setAdapter(mSettingItemAdapter);
+ requestCaptureScreen();
+ ColorPickConfig.setColorPickOpen(getContext(), true);
}
private boolean requestCaptureScreen() {
@@ -89,23 +50,25 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
showColorPicker(data);
finish();
} else {
- mSettingItem.isChecked = true;
- mSettingItemAdapter.notifyDataSetChanged();
+ showToast("start color pick fail");
+ finish();
}
}
private void showColorPicker(Intent data) {
PageIntent pageIntent = new PageIntent(ColorPickerInfoFloatPage.class);
pageIntent.tag = PageTag.PAGE_COLOR_PICKER_INFO;
+ pageIntent.mode = PageIntent.MODE_SINGLE_INSTANCE;
FloatPageManager.getInstance().add(pageIntent);
pageIntent = new PageIntent(ColorPickerFloatPage.class);
pageIntent.bundle = data.getExtras();
+ pageIntent.mode = PageIntent.MODE_SINGLE_INSTANCE;
FloatPageManager.getInstance().add(pageIntent);
}
@Override
protected int onRequestLayout() {
- return R.layout.fragment_color_picker_setting;
+ return R.layout.dk_fragment_color_picker_setting;
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ImageCapture.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ImageCapture.java
index c6c86ebbe..be2048e26 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ImageCapture.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/colorpick/ImageCapture.java
@@ -43,9 +43,10 @@ public void init(Context context, Bundle bundle) {
}
int width = UIUtils.getWidthPixels(context);
int height = UIUtils.getRealHeightPixels(context);
+ int dpi = UIUtils.getDensityDpi(context);
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);
mMediaProjection.createVirtualDisplay("ScreenCapture",
- width, height, UIUtils.getDensityDpi(context),
+ width, height, dpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
}
@@ -65,15 +66,32 @@ public void capture() {
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
- int rowPadding = rowStride - pixelStride * width;
- mBitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
- mBitmap.copyPixelsFromBuffer(buffer);
+ int rowPaddingStride = rowStride - pixelStride * width;
+ int rowPadding = rowPaddingStride / pixelStride;
+ Bitmap recordBitmap = Bitmap.createBitmap(width + rowPadding , height, Bitmap.Config.ARGB_8888);
+ recordBitmap.copyPixelsFromBuffer(buffer);
+ mBitmap = Bitmap.createBitmap(recordBitmap, 0, 0, width, height);
image.close();
isCapturing = false;
}
- public Bitmap getBitmap() {
- return mBitmap;
+ public Bitmap getPartBitmap(int x, int y, int width, int height) {
+ if (mBitmap == null) {
+ return null;
+ }
+ if (x < 0) {
+ x = 0;
+ }
+ if (x + width > mBitmap.getWidth()) {
+ x = mBitmap.getWidth() - width;
+ }
+ if (y < 0) {
+ y = 0;
+ }
+ if (y + height > mBitmap.getHeight()) {
+ y = mBitmap.getHeight() - height;
+ }
+ return Bitmap.createBitmap(mBitmap, x, y, width, height);
}
public void destroy() {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java
index 112c9304a..1ebc153e0 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java
@@ -15,8 +15,6 @@
import android.widget.Toast;
import com.didichuxing.doraemonkit.R;
-import com.didichuxing.doraemonkit.adb.AdbManager;
-import com.didichuxing.doraemonkit.adb.Callback;
import com.didichuxing.doraemonkit.util.FileManager;
import com.didichuxing.doraemonkit.util.LogHelper;
@@ -36,7 +34,7 @@ public class PerformanceDataManager {
private static final String TAG = "PerformanceDataManager";
private static final float SECOND_IN_NANOS = 1000000000f;
private static final int NORMAL_FRAME_RATE = 1;
- private String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/doraemon/";
+ private String filePath;
private String memoryFileName = "memory.txt";
private String cpuFileName = "cpu.txt";
private String fpsFileName = "fps.txt";
@@ -80,31 +78,12 @@ public void doFrame(long frameTimeNanos) {
}
};
- private void excuteCpuData() {
+ private void executeCpuData() {
LogHelper.d(TAG, "current thread name is ==" + Thread.currentThread().getName());
if (mAboveAndroidO) {
- //8.0之后由于权限问题只能通过adb的方式获取
- AdbManager.getInstance().performAdbRequest("shell:dumpsys cpuinfo | grep '" + mPackageName + "'",
- new Callback() {
- @Override
- public void onSuccess(String adbResponse) {
- LogHelper.d(TAG, "response is " + adbResponse);
- try {
- mLastCpuRate = parseCPUData(adbResponse);
- writeCpuDataIntoFile();
- } catch (IOException e) {
- LogHelper.d(TAG, "parse data fail " + e.getMessage());
- mHandler.sendEmptyMessage(MSG_REMIND);
- e.printStackTrace();
- }
- }
-
- @Override
- public void onFail(String failString) {
- mHandler.sendEmptyMessage(MSG_REMIND);
- LogHelper.d(TAG, "failString is " + failString);
- }
- });
+ mLastCpuRate = getCpuDataForO();
+ LogHelper.d(TAG, "cpu info is =" + mLastCpuRate);
+ writeCpuDataIntoFile();
} else {
mLastCpuRate = getCPUData();
LogHelper.d(TAG, "cpu info is =" + mLastCpuRate);
@@ -112,35 +91,65 @@ public void onFail(String failString) {
}
}
- private void excuteMemoruData() {
- if (mAboveAndroidO) {
- //8.0之后由于权限问题只能通过adb的方式获取
- AdbManager.getInstance().performAdbRequest("shell:dumpsys meminfo | grep '" + mPackageName + "'",
- new Callback() {
- @Override
- public void onSuccess(String adbResponse) {
- LogHelper.d(TAG, "response is " + adbResponse);
- try {
- mLastMemoryInfo = parseMemoryData(adbResponse);
- writeMemoryDataIntoFile();
- } catch (IOException e) {
- mHandler.sendEmptyMessage(MSG_REMIND);
- LogHelper.d(TAG, "parse data fail " + e.getMessage());
- e.printStackTrace();
- }
- }
+ private float getCpuDataForO() {
+ java.lang.Process process = null;
+ try {
+ process = Runtime.getRuntime().exec("top -n 1");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line;
+ int cpuIndex = -1;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (TextUtils.isEmpty(line)) {
+ continue;
+ }
+ int tempIndex = getCPUIndex(line);
+ if (tempIndex != -1) {
+ cpuIndex = tempIndex;
+ continue;
+ }
+ if (line.startsWith(String.valueOf(Process.myPid()))) {
+ if (cpuIndex == -1) {
+ continue;
+ }
+ String[] param = line.split("\\s+");
+ if (param.length <= cpuIndex) {
+ continue;
+ }
+ String cpu = param[cpuIndex];
+ if (cpu.endsWith("%")) {
+ cpu = cpu.substring(0, cpu.lastIndexOf("%"));
+ }
+ float rate = Float.parseFloat(cpu) / Runtime.getRuntime().availableProcessors();
+ return rate;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (process != null) {
+ process.destroy();
+ }
+ }
+ return 0;
+ }
- @Override
- public void onFail(String failString) {
- mHandler.sendEmptyMessage(MSG_REMIND);
- LogHelper.d(TAG, "failString is " + failString);
- }
- });
- } else {
- mLastMemoryInfo = getMemoryData();
- LogHelper.d(TAG, "memory info is =" + mLastMemoryInfo);
- writeMemoryDataIntoFile();
+ private int getCPUIndex(String line) {
+ if (line.contains("CPU")) {
+ String[] titles = line.split("\\s+");
+ for (int i = 0; i < titles.length; i++) {
+ if (titles[i].contains("CPU")) {
+ return i;
+ }
+ }
}
+ return -1;
+ }
+
+ private void executeMemoryData() {
+ mLastMemoryInfo = getMemoryData();
+ LogHelper.d(TAG, "memory info is =" + mLastMemoryInfo);
+ writeMemoryDataIntoFile();
}
private void remindUserToConnectPort() {
@@ -163,11 +172,11 @@ public static PerformanceDataManager getInstance() {
public void init(Context context) {
mContext = context;
+ filePath = getFilePath(context);
mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAboveAndroidO = true;
mPackageName = context.getPackageName();
- AdbManager.getInstance().init(context);
}
if (mHandlerThread == null) {
mHandlerThread = new HandlerThread("handler-thread");
@@ -179,10 +188,10 @@ public void init(Context context) {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MSG_CPU) {
- excuteCpuData();
+ executeCpuData();
mHandler.sendEmptyMessageDelayed(MSG_CPU, NORMAL_FRAME_RATE * 1000);
} else if (msg.what == MSG_MEMORY) {
- excuteMemoruData();
+ executeMemoryData();
mHandler.sendEmptyMessageDelayed(MSG_MEMORY, NORMAL_FRAME_RATE * 1000);
} else if (msg.what == MSG_REMIND) {
remindUserToConnectPort();
@@ -192,6 +201,15 @@ public void handleMessage(Message msg) {
}
}
+ private String getFilePath(Context context) {
+ boolean hasExternalStorage = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
+ if (hasExternalStorage) {
+ return context.getExternalFilesDir(null).getAbsolutePath() + "/doraemon/";
+ } else {
+ return Environment.getExternalStorageDirectory().getAbsolutePath() + "/doraemon/";
+ }
+ }
+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void startMonitorFrameInfo() {
Choreographer.getInstance().postFrameCallback(mFrameCallback);
@@ -286,7 +304,7 @@ private float getCPUData() {
mLastCpuTime = cpuTime;
mLastAppCpuTime = appTime;
} catch (Exception e) {
- e.printStackTrace();
+ LogHelper.e(TAG,"getCPUData fail: "+e.toString());
}
return value;
}
@@ -305,7 +323,7 @@ private float getMemoryData() {
}
}
} catch (Exception e) {
- e.printStackTrace();
+ LogHelper.e(TAG,"getMemoryData fail: "+e.toString());
}
return mem;
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceFragment.java
index b41d17b64..170bcfc9c 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceFragment.java
@@ -38,7 +38,7 @@ public class PerformanceFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_cpu_cache_log;
+ return R.layout.dk_fragment_cpu_cache_log;
}
@Override
@@ -89,7 +89,7 @@ public void onRightClick() {
new LoadDataTask().execute(PerformanceDataManager.getInstance().getFpsFilePath());
} else {
builder.setMaxValue(100).setMinValue(0);
- model.setText(R.string.dk_frameinfo_cpu);
+ model.setText(R.string.dk_fragment_parameter);
new LoadDataTask().execute(PerformanceDataManager.getInstance().getCpuFilePath());
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/cpu/CpuMainPageFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/cpu/CpuMainPageFragment.java
deleted file mode 100644
index d821aa3e9..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/cpu/CpuMainPageFragment.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.didichuxing.doraemonkit.kit.cpu;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
-import android.view.View;
-
-import com.didichuxing.doraemonkit.R;
-import com.didichuxing.doraemonkit.config.PerformanceInfoConfig;
-import com.didichuxing.doraemonkit.constant.BundleKey;
-import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager;
-import com.didichuxing.doraemonkit.kit.common.PerformanceFragment;
-import com.didichuxing.doraemonkit.ui.base.BaseFragment;
-import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory;
-import com.didichuxing.doraemonkit.ui.realtime.OnFloatPageChangeListener;
-import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartIconPage;
-import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartPage;
-import com.didichuxing.doraemonkit.ui.setting.SettingItem;
-import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
-import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
-
-public class CpuMainPageFragment extends BaseFragment implements OnFloatPageChangeListener {
- private static final String TAG = "CpuMainPageFragment";
- private SettingItemAdapter mSettingItemAdapter;
- private RecyclerView mSettingList;
-
- @Override
- protected int onRequestLayout() {
- return R.layout.fragment_cpu_main_page;
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- PerformanceDataManager.getInstance().init(getContext().getApplicationContext());
- initView();
- }
-
- private void initView() {
- HomeTitleBar titleBar = findViewById(R.id.title_bar);
- titleBar.setTitle(R.string.dk_frameinfo_cpu);
- titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() {
- @Override
- public void onRightClick() {
- getActivity().finish();
- }
- });
-
- mSettingList = findViewById(R.id.setting_list);
- mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
- mSettingItemAdapter = new SettingItemAdapter(getContext());
- mSettingItemAdapter.append(new SettingItem(R.string.dk_cpu_detection_switch, PerformanceInfoConfig.isCPUOpen(getContext())));
- mSettingItemAdapter.append(new SettingItem(R.string.dk_item_cache_log, R.drawable.dk_more_icon));
-
- mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
- @Override
- public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
- if (data.desc == R.string.dk_cpu_detection_switch) {
- if (on) {
- startMonitor();
- } else {
- stopMonitor();
- }
- PerformanceInfoConfig.setCPUOpen(getContext(), on);
- }
- }
- });
- mSettingItemAdapter.setOnSettingItemClickListener(new SettingItemAdapter.OnSettingItemClickListener() {
- @Override
- public void onSettingItemClick(View view, SettingItem data) {
- if (data.desc == R.string.dk_item_cache_log) {
- Bundle bundle = new Bundle();
- bundle.putInt(BundleKey.PERFORMANCE_TYPE, PerformanceFragment.CPU);
- showContent(PerformanceFragment.class, bundle);
- }
- }
- });
- mSettingList.setAdapter(mSettingItemAdapter);
-// if (PerformanceInfoConfig.isCPUOpen(getContext())) {
-// startMonitor();
-// }
- }
-
- private void startMonitor() {
- PerformanceDataManager.getInstance().startMonitorCPUInfo();
- String title = getString(R.string.dk_frameinfo_cpu);
- int type = DataSourceFactory.TYPE_CPU;
- RealTimeChartPage.openChartPage(title, type, RealTimeChartPage.DEFAULT_REFRESH_INTERVAL,this);
- }
-
- private void stopMonitor() {
- PerformanceDataManager.getInstance().stopMonitorCPUInfo();
- RealTimeChartPage.closeChartPage();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- RealTimeChartPage.removeCloseListener();
- }
-
- @Override
- public void onFloatPageClose(String tag) {
- if (!TextUtils.equals(RealTimeChartIconPage.TAG, tag)) {
- return;
- }
- if (mSettingList == null || mSettingList.isComputingLayout()) {
- return;
- }
- if (mSettingItemAdapter == null) {
- return;
- }
- if (!mSettingItemAdapter.getData().get(0).isChecked) {
- return;
- }
- mSettingItemAdapter.getData().get(0).isChecked = false;
- mSettingItemAdapter.notifyItemChanged(0);
- }
-
- @Override
- public void onFloatPageOpen(String tag) {
-
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java
index 20afce141..0b1d07752 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java
@@ -27,7 +27,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
@Override
protected int onRequestLayout() {
- return R.layout.fragment_crash_capture;
+ return R.layout.dk_fragment_crash_capture;
}
private void initView() {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java
index 38d3fe3a3..a31bbfc4b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java
@@ -17,7 +17,7 @@
public class CrashCaptureMainFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_crash_capture_main;
+ return R.layout.dk_fragment_crash_capture_main;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashDetailFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashDetailFragment.java
index 6cc149b74..39868945b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashDetailFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashDetailFragment.java
@@ -30,7 +30,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
@Override
protected int onRequestLayout() {
- return R.layout.fragment_crash_detail_info;
+ return R.layout.dk_fragment_crash_detail_info;
}
private void initView() {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/dataclean/DataCleanFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/dataclean/DataCleanFragment.java
index 384ef2dbf..fbbe94a71 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/dataclean/DataCleanFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/dataclean/DataCleanFragment.java
@@ -29,7 +29,7 @@ public class DataCleanFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_data_clean;
+ return R.layout.dk_fragment_data_clean;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/DBDetailFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/DBDetailFragment.java
new file mode 100644
index 000000000..986c7ac29
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/DBDetailFragment.java
@@ -0,0 +1,101 @@
+package com.didichuxing.doraemonkit.kit.fileexplorer;
+
+import android.database.sqlite.SQLiteDatabase;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.constant.BundleKey;
+import com.didichuxing.doraemonkit.ui.base.BaseFragment;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.ArrayTableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.format.FastTextDrawFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.style.FontStyle;
+import com.didichuxing.doraemonkit.ui.widget.tableview.component.SmartTable;
+import com.didichuxing.doraemonkit.ui.widget.titlebar.TitleBar;
+import com.didichuxing.doraemonkit.util.DBUtil;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class DBDetailFragment extends BaseFragment {
+
+ private SmartTable table;
+ private ListView tableListView;
+
+ @Override
+ protected int onRequestLayout() {
+ return R.layout.dk_fragment_db_detail;
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ Bundle data = getArguments();
+ SQLiteDatabase sqLiteDatabase = null;
+ List tableNames = new ArrayList<>();
+ if (data != null) {
+ File mFile = (File) data.getSerializable(BundleKey.FILE_KEY);
+ String path = mFile.getPath();
+ sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(path, null);
+ tableNames = DBUtil.queryDBtableName(sqLiteDatabase);
+ }
+ table = findViewById(R.id.table);
+ FontStyle fontStyle = new FontStyle(getContext(), 15, ContextCompat.getColor(getContext(), R.color.dk_color_000000));
+ TableConfig.getInstance().setVerticalPadding(10).setHorizontalPadding(10);
+ TableConfig.getInstance().columnTitleStyle = fontStyle;
+ table.setZoom(true, 2f, 0.4f);
+
+
+ tableListView = findViewById(R.id.lv_table_name);
+ tableListView.setAdapter(new DBListAdapter(getContext(), tableNames));
+ final List finalStrings = tableNames;
+ final SQLiteDatabase finalSqLiteDatabase = sqLiteDatabase;
+ TitleBar titleBar = findViewById(R.id.title_bar);
+ titleBar.setOnTitleBarClickListener(new TitleBar.OnTitleBarClickListener() {
+ @Override
+ public void onLeftClick() {
+ onBackPressed();
+ }
+
+ @Override
+ public void onRightClick() {
+
+ }
+ });
+ tableListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ String selectTableName = finalStrings.get(position);
+
+ String[][] data = DBUtil.queryAll(finalSqLiteDatabase, finalStrings.get(position));
+ String[] titleName = DBUtil.queryTableColumnName(finalSqLiteDatabase, selectTableName);
+ if (table.getTableData() != null) {
+ table.getTableData().clear();
+ }
+ table.setTableData(ArrayTableData.create(selectTableName, titleName, data, new FastTextDrawFormat()));
+ table.getMatrixHelper().reset();
+ tableListView.setVisibility(View.GONE);
+ table.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+
+ @Override
+ protected boolean onBackPressed() {
+ if (table.getVisibility() == View.VISIBLE) {
+ table.setVisibility(View.GONE);
+ tableListView.setVisibility(View.VISIBLE);
+ } else {
+ finish();
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/DBListAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/DBListAdapter.java
new file mode 100644
index 000000000..bf5fc73de
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/DBListAdapter.java
@@ -0,0 +1,63 @@
+package com.didichuxing.doraemonkit.kit.fileexplorer;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.didichuxing.doraemonkit.R;
+
+import java.util.List;
+
+public class DBListAdapter extends BaseAdapter {
+ private List data;
+ private Context context;
+
+ public DBListAdapter(Context context, List data) {
+ this.data = data;
+ this.context = context;
+ }
+
+ @Override
+ public int getCount() {
+ return data.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return data.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ convertView = LayoutInflater.from(context).inflate(R.layout.dk_item_file_info, null);
+ convertView.setTag(new ViewHolder(convertView));
+ }
+ viewHolder = (ViewHolder) convertView.getTag();
+ viewHolder.setData((String) data.get(position));
+ return convertView;
+ }
+
+ public class ViewHolder {
+ public TextView textView;
+
+ public ViewHolder(View convertView) {
+ textView = (TextView) convertView.findViewById(R.id.name);
+ convertView.findViewById(R.id.icon).setVisibility(View.GONE);
+
+ }
+
+ public void setData(String data) {
+ textView.setText(data);
+ }
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/FileExplorerFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/FileExplorerFragment.java
index 3328b9357..aff654140 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/FileExplorerFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/FileExplorerFragment.java
@@ -55,6 +55,8 @@ public void onViewClick(View v, FileInfo fileInfo) {
bundle.putSerializable(BundleKey.FILE_KEY, fileInfo.file);
if (FileUtil.isImage(fileInfo.file)) {
showContent(ImageDetailFragment.class, bundle);
+ } else if (FileUtil.isDB(fileInfo.file)) {
+ showContent(DBDetailFragment.class, bundle);
} else {
showContent(TextDetailFragment.class, bundle);
}
@@ -89,6 +91,9 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
private List getFileInfos(File dir) {
List fileInfos = new ArrayList<>();
+ if (dir.listFiles() == null) {
+ return fileInfos;
+ }
for (File file : dir.listFiles()) {
FileInfo fileInfo = new FileInfo(file);
fileInfos.add(fileInfo);
@@ -98,7 +103,7 @@ private List getFileInfos(File dir) {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_file_explorer;
+ return R.layout.dk_fragment_file_explorer;
}
@Override
@@ -106,7 +111,8 @@ protected boolean onBackPressed() {
if (mCurDir == null) {
getActivity().finish();
return true;
- } if (isRootFile(getContext(), mCurDir)) {
+ }
+ if (isRootFile(getContext(), mCurDir)) {
mTitleBar.setTitle(R.string.dk_kit_file_explorer);
setAdapterData(initRootFileInfos(getContext()));
mCurDir = null;
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/ImageDetailFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/ImageDetailFragment.java
index 2ec277398..c24e201d8 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/ImageDetailFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/ImageDetailFragment.java
@@ -46,7 +46,7 @@ private void readImage(File file) {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_image_detail;
+ return R.layout.dk_fragment_image_detail;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/TextDetailFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/TextDetailFragment.java
index d634379a9..6848c7f23 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/TextDetailFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/TextDetailFragment.java
@@ -73,7 +73,7 @@ private void readFile(File file) {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_text_detail;
+ return R.layout.dk_fragment_text_detail;
}
private static class FileReadTask extends AsyncTask {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/frameInfo/FrameInfoFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/frameInfo/FrameInfoFragment.java
deleted file mode 100644
index 965f40002..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/frameInfo/FrameInfoFragment.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.didichuxing.doraemonkit.kit.frameInfo;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
-import android.view.View;
-
-import com.didichuxing.doraemonkit.R;
-import com.didichuxing.doraemonkit.config.PerformanceInfoConfig;
-import com.didichuxing.doraemonkit.constant.BundleKey;
-import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager;
-import com.didichuxing.doraemonkit.kit.common.PerformanceFragment;
-import com.didichuxing.doraemonkit.ui.base.BaseFragment;
-import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory;
-import com.didichuxing.doraemonkit.ui.realtime.OnFloatPageChangeListener;
-import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartIconPage;
-import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartPage;
-import com.didichuxing.doraemonkit.ui.setting.SettingItem;
-import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
-import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
-
-/**
- * Created by wanglikun on 2018/9/13.
- */
-
-public class FrameInfoFragment extends BaseFragment implements OnFloatPageChangeListener {
-
- private SettingItemAdapter mSettingItemAdapter;
- private RecyclerView mSettingList;
-
- @Override
- protected int onRequestLayout() {
- return R.layout.fragment_frame_info;
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- initView();
- }
-
- private void initView() {
- HomeTitleBar titleBar = findViewById(R.id.title_bar);
- titleBar.setTitle(R.string.dk_kit_frame_info_desc);
- titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() {
- @Override
- public void onRightClick() {
- getActivity().finish();
- }
- });
-
- mSettingList = findViewById(R.id.setting_list);
- mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
- mSettingItemAdapter = new SettingItemAdapter(getContext());
- mSettingItemAdapter.append(new SettingItem(R.string.dk_frameinfo_detection_switch, PerformanceInfoConfig.isFPSOpen(getContext())));
- mSettingItemAdapter.append(new SettingItem(R.string.dk_item_cache_log, R.drawable.dk_more_icon));
-
- mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
- @Override
- public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
- if (data.desc == R.string.dk_frameinfo_detection_switch) {
- if (on) {
- startMonitor();
- } else {
- stopMonitor();
- }
- PerformanceInfoConfig.setFPSOpen(getContext(), on);
- }
- }
- });
- mSettingItemAdapter.setOnSettingItemClickListener(new SettingItemAdapter.OnSettingItemClickListener() {
- @Override
- public void onSettingItemClick(View view, SettingItem data) {
- if (data.desc == R.string.dk_item_cache_log) {
-
- Bundle bundle = new Bundle();
- bundle.putInt(BundleKey.PERFORMANCE_TYPE, PerformanceFragment.FPS);
- showContent(PerformanceFragment.class, bundle);
- }
-
- }
- });
- mSettingList.setAdapter(mSettingItemAdapter);
-// if (PerformanceInfoConfig.isFPSOpen(getContext())) {
-// startMonitor();
-// }
- }
-
- private void startMonitor() {
- PerformanceDataManager.getInstance().startMonitorFrameInfo();
- String title = getString(R.string.dk_frameinfo_fps);
- int type = DataSourceFactory.TYPE_FRAME;
- RealTimeChartPage.openChartPage(title, type, RealTimeChartPage.DEFAULT_REFRESH_INTERVAL, this);
- }
-
- private void stopMonitor() {
- PerformanceDataManager.getInstance().stopMonitorFrameInfo();
- RealTimeChartPage.closeChartPage();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- RealTimeChartPage.removeCloseListener();
- }
-
- @Override
- public void onFloatPageClose(String tag) {
- if (!TextUtils.equals(RealTimeChartIconPage.TAG, tag)) {
- return;
- }
- if (mSettingList == null || mSettingList.isComputingLayout()) {
- return;
- }
- if (mSettingItemAdapter == null) {
- return;
- }
- if (!mSettingItemAdapter.getData().get(0).isChecked) {
- return;
- }
- mSettingItemAdapter.getData().get(0).isChecked = false;
- mSettingItemAdapter.notifyItemChanged(0);
- }
-
- @Override
- public void onFloatPageOpen(String tag) {
-
- }
-}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsHookManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsHookManager.java
index 72fc06ab0..f36e2002a 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsHookManager.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsHookManager.java
@@ -20,13 +20,19 @@
public class GpsHookManager {
private static final String TAG = "GpsHookManager";
- private Location mLocation;
+ private double mLatitude = -1;
+ private double mLongitude = -1;
private boolean isMockEnable;
+
private boolean isMocking;
- public Location getLocation() {
- return mLocation;
+ public void startMock() {
+ isMocking = true;
+ }
+
+ public void stopMock() {
+ isMocking = false;
}
private static class Holder {
@@ -38,12 +44,11 @@ public static GpsHookManager getInstance() {
}
private GpsHookManager() {
- mLocation = new Location(LocationManager.GPS_PROVIDER);
}
public void mockLocation(double latitude, double longitude) {
- mLocation.setLatitude(latitude);
- mLocation.setLongitude(longitude);
+ mLatitude = latitude;
+ mLongitude= longitude;
}
@SuppressLint("PrivateApi")
@@ -72,17 +77,16 @@ public void init() {
}
}
-
- public void startMock() {
- this.isMocking = true;
+ public boolean isMocking() {
+ return isMocking && mLongitude != -1 && mLatitude != -1;
}
- public void stopMock() {
- this.isMocking = false;
+ public double getLatitude() {
+ return mLatitude;
}
- public boolean isMocking() {
- return isMocking;
+ public double getLongitude() {
+ return mLongitude;
}
public boolean isMockEnable() {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMock.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMock.java
index 370da6fe6..9edb4bb9b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMock.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMock.java
@@ -4,6 +4,7 @@
import android.content.Intent;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.GpsMockConfig;
import com.didichuxing.doraemonkit.constant.BundleKey;
import com.didichuxing.doraemonkit.constant.FragmentIndex;
import com.didichuxing.doraemonkit.kit.Category;
@@ -40,7 +41,6 @@ public void onClick(Context context) {
@Override
public void onAppInit(Context context) {
-
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockFragment.java
index 9733c1900..296f1a6f8 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockFragment.java
@@ -34,11 +34,18 @@ public class GpsMockFragment extends BaseFragment implements SettingItemAdapter.
private HomeTitleBar mTitleBar;
private RecyclerView mSettingList;
private SettingItemAdapter mSettingItemAdapter;
- private View mMockLocationArea;
private EditText mLongitude;
private EditText mLatitude;
private TextView mMockLocationBtn;
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (GpsMockConfig.isGPSMockOpen(getContext())) {
+ GpsHookManager.getInstance().startMock();
+ }
+ }
+
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -48,7 +55,6 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
}
private void initMockLocationArea() {
- mMockLocationArea = findViewById(R.id.mock_location_area);
mLongitude = findViewById(R.id.longitude);
mLatitude = findViewById(R.id.latitude);
mLatitude.addTextChangedListener(new TextWatcher() {
@@ -152,19 +158,17 @@ private void intiSettingList() {
@Override
public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
if (data.desc == R.string.dk_gpsmock_open) {
+ GpsMockConfig.setGPSMockOpen(getContext(), on);
if (on) {
GpsHookManager.getInstance().startMock();
- mMockLocationArea.setVisibility(View.VISIBLE);
} else {
GpsHookManager.getInstance().stopMock();
- mMockLocationArea.setVisibility(View.GONE);
}
- GpsMockConfig.setGPSMockOpen(getContext(), on);
}
}
@Override
protected int onRequestLayout() {
- return R.layout.fragment_gps_mock;
+ return R.layout.dk_fragment_gps_mock;
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockManager.java
index 4346a8e3d..ed51b129f 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockManager.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/GpsMockManager.java
@@ -31,8 +31,6 @@ public class GpsMockManager {
private List mMockProviders = new CopyOnWriteArrayList<>();
- private List mLocationListeners = new ArrayList<>();
-
private Location mLocation;
private boolean isMock;
@@ -40,34 +38,6 @@ public class GpsMockManager {
private double mLatitude = -1;
private double mLongitude = -1;
- private LocationListener mLocationListener = new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- String provider = location.getProvider();
- String content = "lat(" + location.getLatitude() + ") lng(" + location.getLongitude() + ")";
- LogHelper.d(TAG, provider + " : " + content);
- mLocation = location;
- for (LocationListener locationListener : mLocationListeners) {
- locationListener.onLocationChanged(location);
- }
- }
-
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
-
- }
-
- @Override
- public void onProviderEnabled(String provider) {
-
- }
-
- @Override
- public void onProviderDisabled(String provider) {
-
- }
- };
-
public boolean isMock() {
return isMock;
}
@@ -93,9 +63,6 @@ public void init(Context context) {
}
mMockProviders.add(LocationManager.GPS_PROVIDER);
mMockProviders.add(LocationManager.NETWORK_PROVIDER);
-
- mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5, mLocationListener);
- mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 5, mLocationListener);
}
public void startMock() {
@@ -174,20 +141,10 @@ public void stopMock() {
public void destroy() {
stopMock();
isMock = false;
- mLocationManager.removeUpdates(mLocationListener);
mMockProviders.clear();
- mLocationListeners.clear();
mLocation = null;
}
- public void addLocationListener(LocationListener listener) {
- mLocationListeners.add(listener);
- }
-
- public void removeLocationListener(LocationListener listener) {
- mLocationListeners.remove(listener);
- }
-
public Location getLocation() {
return mLocation;
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/LocationHookHandler.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/LocationHookHandler.java
index 57d32b117..ce86ffb2f 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/LocationHookHandler.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/gpsmock/LocationHookHandler.java
@@ -2,10 +2,14 @@
import android.annotation.SuppressLint;
import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
import android.os.IBinder;
import com.didichuxing.doraemonkit.util.LogHelper;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
@@ -22,7 +26,7 @@ public class LocationHookHandler implements InvocationHandler {
@SuppressLint("PrivateApi")
public LocationHookHandler(IBinder binder) {
try {
- Class iLocationManager$Stub = Class.forName("android.location.ILocationManager$Stub");
+ Class iLocationManager$Stub = Class.forName("android.location.ILocationManager$Stub");
Method asInterface = iLocationManager$Stub.getDeclaredMethod("asInterface", IBinder.class);
this.mOriginService = asInterface.invoke(null, binder);
} catch (Exception e) {
@@ -32,19 +36,63 @@ public LocationHookHandler(IBinder binder) {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (GpsHookManager.getInstance().isMocking()) {
- switch (method.getName()) {
- case "getLastLocation":
- Location lastLocation = GpsHookManager.getInstance().getLocation();
- lastLocation.setTime(System.currentTimeMillis());
- return lastLocation;
- case "getLastKnownLocation":
- Location lastKnownLocation = GpsHookManager.getInstance().getLocation();
- lastKnownLocation.setTime(System.currentTimeMillis());
- return lastKnownLocation;
- default:
+ switch (method.getName()) {
+ case "requestLocationUpdates":
+ Field[] fields = args[1].getClass().getDeclaredFields();
+ for (Field field : fields) {
+ if (field.getType() == LocationListener.class) {
+ field.setAccessible(true);
+ final LocationListener originalLocationListener = (LocationListener) field.get(args[1]);
+ LocationListener newLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (!GpsHookManager.getInstance().isMocking()) {
+ originalLocationListener.onLocationChanged(location);
+ } else {
+ location.setLongitude(GpsHookManager.getInstance().getLongitude());
+ location.setLatitude(GpsHookManager.getInstance().getLatitude());
+ originalLocationListener.onLocationChanged(location);
+ }
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ originalLocationListener.onStatusChanged(provider, status, extras);
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ originalLocationListener.onProviderEnabled(provider);
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ originalLocationListener.onProviderDisabled(provider);
+ }
+ };
+ field.set(args[1], newLocationListener);
+ field.setAccessible(false);
+ }
+ }
+ break;
+ case "getLastLocation":
+ if (!GpsHookManager.getInstance().isMocking()) {
+ break;
+ }
+ Location lastLocation = (Location) method.invoke(this.mOriginService, args);
+ lastLocation.setLongitude(GpsHookManager.getInstance().getLongitude());
+ lastLocation.setLatitude(GpsHookManager.getInstance().getLatitude());
+ return lastLocation;
+ case "getLastKnownLocation":
+ if (!GpsHookManager.getInstance().isMocking()) {
break;
- }
+ }
+ Location lastKnownLocation = (Location) method.invoke(this.mOriginService, args);
+ lastKnownLocation.setLongitude(GpsHookManager.getInstance().getLongitude());
+ lastKnownLocation.setLatitude(GpsHookManager.getInstance().getLatitude());
+ return lastKnownLocation;
+ default:
+ break;
}
return method.invoke(this.mOriginService, args);
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorder.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorder.java
new file mode 100644
index 000000000..8a2de9b84
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorder.java
@@ -0,0 +1,46 @@
+package com.didichuxing.doraemonkit.kit.layoutborder;
+
+import android.content.Context;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.LayoutBorderConfig;
+import com.didichuxing.doraemonkit.kit.Category;
+import com.didichuxing.doraemonkit.kit.IKit;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.PageIntent;
+
+/**
+ * Created by wanglikun on 2019/1/7
+ */
+public class LayoutBorder implements IKit {
+ @Override
+ public int getCategory() {
+ return Category.UI;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_kit_layout_border;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.drawable.dk_view_border;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ LayoutBorderManager.getInstance().start();
+ LayoutBorderConfig.setLayoutBorderOpen(true);
+ PageIntent intent = new PageIntent(LayoutLevelFloatPage.class);
+ intent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(intent);
+ LayoutBorderConfig.setLayoutLevelOpen(true);
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+ LayoutBorderConfig.setLayoutBorderOpen(false);
+ LayoutBorderConfig.setLayoutLevelOpen(false);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorderManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorderManager.java
new file mode 100644
index 000000000..44ef376a7
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorderManager.java
@@ -0,0 +1,86 @@
+package com.didichuxing.doraemonkit.kit.layoutborder;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+
+import com.didichuxing.doraemonkit.DoraemonKit;
+import com.didichuxing.doraemonkit.ui.UniversalActivity;
+import com.didichuxing.doraemonkit.ui.layoutborder.ViewBorderFrameLayout;
+
+/**
+ * Created by wanglikun on 2019/1/9
+ */
+public class LayoutBorderManager {
+ private boolean isRunning;
+
+ private ViewBorderFrameLayout mViewBorderFrameLayout;
+
+ private DoraemonKit.ActivityLifecycleListener mLifecycleListener = new DoraemonKit.ActivityLifecycleListener() {
+ @Override
+ public void onActivityResumed(Activity activity) {
+ resolveActivity(activity);
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+
+ }
+ };
+
+ private void resolveActivity(Activity activity) {
+ if (activity == null || (activity instanceof UniversalActivity)) {
+ return;
+ }
+ Window window = activity.getWindow();
+ if (window == null) {
+ return;
+ }
+ final ViewGroup root = (ViewGroup) window.getDecorView();
+ if (root == null) {
+ return;
+ }
+ mViewBorderFrameLayout = new ViewBorderFrameLayout(root.getContext());
+ while (root.getChildCount() != 0) {
+ View child = root.getChildAt(0);
+ if (child instanceof ViewBorderFrameLayout) {
+ mViewBorderFrameLayout = (ViewBorderFrameLayout) child;
+ return;
+ }
+ root.removeView(child);
+ mViewBorderFrameLayout.addView(child);
+ }
+ root.addView(mViewBorderFrameLayout);
+ }
+
+ private static class Holder {
+ private static LayoutBorderManager INSTANCE = new LayoutBorderManager();
+ }
+
+ private LayoutBorderManager() {
+ }
+
+ public static LayoutBorderManager getInstance() {
+ return Holder.INSTANCE;
+ }
+
+ public void start() {
+ isRunning = true;
+ resolveActivity(DoraemonKit.getCurrentResumedActivity());
+ DoraemonKit.registerListener(mLifecycleListener);
+ }
+
+ public void stop() {
+ isRunning = false;
+ if (mViewBorderFrameLayout != null) {
+ mViewBorderFrameLayout.requestLayout();
+ }
+ mViewBorderFrameLayout = null;
+ DoraemonKit.unRegisterListener(mLifecycleListener);
+ }
+
+ public boolean isRunning() {
+ return isRunning;
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorderSettingFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorderSettingFragment.java
new file mode 100644
index 000000000..f0fc3ec7f
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutBorderSettingFragment.java
@@ -0,0 +1,76 @@
+package com.didichuxing.doraemonkit.kit.layoutborder;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.LayoutBorderConfig;
+import com.didichuxing.doraemonkit.ui.base.BaseFragment;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.PageIntent;
+import com.didichuxing.doraemonkit.ui.setting.SettingItem;
+import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
+import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
+
+/**
+ * Created by wanglikun on 2018/10/9.
+ */
+
+public class LayoutBorderSettingFragment extends BaseFragment {
+ private static final String TAG = "LayoutBorderSettingFragment";
+ private RecyclerView mSettingList;
+ private SettingItemAdapter mSettingItemAdapter;
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ initView();
+ }
+
+ private void initView() {
+ HomeTitleBar titleBar = findViewById(R.id.title_bar);
+ titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() {
+ @Override
+ public void onRightClick() {
+ finish();
+ }
+ });
+ mSettingList = findViewById(R.id.setting_list);
+ mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
+ mSettingItemAdapter = new SettingItemAdapter(getContext());
+ mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_layout_border, LayoutBorderConfig.isLayoutBorderOpen()));
+ mSettingItemAdapter.append(new SettingItem(R.string.dk_layout_level, LayoutBorderConfig.isLayoutLevelOpen()));
+ mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
+ @Override
+ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
+ if (data.desc == R.string.dk_kit_layout_border) {
+ if (on) {
+ LayoutBorderManager.getInstance().start();
+ } else {
+ LayoutBorderManager.getInstance().stop();
+ }
+ LayoutBorderConfig.setLayoutBorderOpen(on);
+ } else if (data.desc == R.string.dk_layout_level) {
+ if (on) {
+ PageIntent intent = new PageIntent(LayoutLevelFloatPage.class);
+ intent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(intent);
+ } else {
+ FloatPageManager.getInstance().removeAll(LayoutLevelFloatPage.class);
+ }
+ LayoutBorderConfig.setLayoutLevelOpen(on);
+ }
+ }
+ });
+ mSettingList.setAdapter(mSettingItemAdapter);
+ }
+
+ @Override
+ protected int onRequestLayout() {
+ return R.layout.dk_fragment_layout_border_setting;
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutLevelFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutLevelFloatPage.java
new file mode 100644
index 000000000..572b40b0d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/layoutborder/LayoutLevelFloatPage.java
@@ -0,0 +1,177 @@
+package com.didichuxing.doraemonkit.kit.layoutborder;
+
+import android.app.Activity;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+import com.didichuxing.doraemonkit.DoraemonKit;
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.LayoutBorderConfig;
+import com.didichuxing.doraemonkit.ui.UniversalActivity;
+import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
+import com.didichuxing.doraemonkit.ui.layoutborder.ScalpelFrameLayout;
+import com.didichuxing.doraemonkit.util.UIUtils;
+
+/**
+ * Created by wanglikun on 2019/1/9
+ */
+public class LayoutLevelFloatPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener {
+ private WindowManager mWindowManager;
+
+ private CheckBox mSwitchButton;
+ private View mClose;
+
+ private TouchProxy mTouchProxy = new TouchProxy(this);
+
+ private ScalpelFrameLayout mScalpelFrameLayout;
+
+ private boolean mIsCheck;
+ private DoraemonKit.ActivityLifecycleListener mLifecycleListener = new DoraemonKit.ActivityLifecycleListener() {
+ @Override
+ public void onActivityResumed(Activity activity) {
+ resolveActivity(activity);
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+
+ }
+ };
+
+ private void resolveActivity(Activity activity) {
+ if (activity == null || (activity instanceof UniversalActivity)) {
+ return;
+ }
+ Window window = activity.getWindow();
+ if (window == null) {
+ return;
+ }
+ final ViewGroup root = (ViewGroup) window.getDecorView();
+ if (root == null) {
+ return;
+ }
+ mScalpelFrameLayout = new ScalpelFrameLayout(root.getContext());
+ while (root.getChildCount() != 0) {
+ View child = root.getChildAt(0);
+ if (child instanceof ScalpelFrameLayout) {
+ mScalpelFrameLayout = (ScalpelFrameLayout) child;
+ return;
+ }
+ root.removeView(child);
+ mScalpelFrameLayout.addView(child);
+ }
+ mScalpelFrameLayout.setLayerInteractionEnabled(mIsCheck);
+ root.addView(mScalpelFrameLayout);
+ }
+
+ @Override
+ protected View onCreateView(Context context, ViewGroup view) {
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_layout_level, view, false);
+ }
+
+ @Override
+ protected void onViewCreated(View view) {
+ super.onViewCreated(view);
+ mSwitchButton = findViewById(R.id.switch_btn);
+ mSwitchButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ if (mScalpelFrameLayout != null) {
+ mScalpelFrameLayout.setLayerInteractionEnabled(true);
+ }
+ } else {
+ if (mScalpelFrameLayout != null) {
+ mScalpelFrameLayout.setLayerInteractionEnabled(false);
+ }
+ }
+ mIsCheck = isChecked;
+ }
+ });
+ mClose = findViewById(R.id.close);
+ mClose.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mScalpelFrameLayout != null) {
+ mScalpelFrameLayout.setLayerInteractionEnabled(false);
+ }
+ FloatPageManager.getInstance().removeAll(LayoutLevelFloatPage.class);
+ LayoutBorderConfig.setLayoutLevelOpen(false);
+
+ LayoutBorderConfig.setLayoutBorderOpen(false);
+ LayoutBorderManager.getInstance().stop();
+ }
+ });
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
+ }
+
+ @Override
+ protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
+ params.x = 0;
+ params.y = UIUtils.getHeightPixels(getContext()) - UIUtils.dp2px(getContext(), 125);
+ params.width = WindowManager.LayoutParams.MATCH_PARENT;
+ params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ }
+
+ @Override
+ protected void onCreate(Context context) {
+ super.onCreate(context);
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ resolveActivity(DoraemonKit.getCurrentResumedActivity());
+ DoraemonKit.registerListener(mLifecycleListener);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mScalpelFrameLayout != null) {
+ mScalpelFrameLayout.setLayerInteractionEnabled(false);
+ mScalpelFrameLayout = null;
+ }
+ DoraemonKit.unRegisterListener(mLifecycleListener);
+ }
+
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
+ }
+
+ @Override
+ public void onEnterForeground() {
+ super.onEnterForeground();
+ getRootView().setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onEnterBackground() {
+ super.onEnterBackground();
+ getRootView().setVisibility(View.GONE);
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfo.java
index 5169182ef..5407e8d55 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfo.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfo.java
@@ -4,6 +4,7 @@
import android.content.Intent;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.LogInfoConfig;
import com.didichuxing.doraemonkit.constant.BundleKey;
import com.didichuxing.doraemonkit.constant.FragmentIndex;
import com.didichuxing.doraemonkit.kit.Category;
@@ -41,7 +42,7 @@ public void onClick(Context context) {
@Override
public void onAppInit(Context context) {
-
+ LogInfoConfig.setLogInfoOpen(context, false);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoFloatPage.java
index f71f6f64b..363ba3558 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoFloatPage.java
@@ -63,7 +63,7 @@ protected void onDestroy() {
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_log_info, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_log_info, null);
}
@Override
@@ -94,10 +94,11 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
@Override
public void afterTextChanged(Editable s) {
if (!TextUtils.isEmpty(mLogFilter.getText())) {
- CharSequence filter = mLogFilter.getText();
+ String filter = mLogFilter.getText().toString();
List infoItems = new ArrayList<>();
for (LogInfoItem item : mLogInfoItems) {
- if (item.orginalLog.contains(filter)) {
+ // 忽略大小写检查
+ if (item.orginalLog.toLowerCase().contains(filter.toLowerCase())) {
infoItems.add(item);
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoSettingFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoSettingFragment.java
index 286a35d3f..5317b1d72 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoSettingFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/logInfo/LogInfoSettingFragment.java
@@ -8,6 +8,7 @@
import android.view.View;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.LogInfoConfig;
import com.didichuxing.doraemonkit.ui.base.BaseFragment;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
import com.didichuxing.doraemonkit.ui.base.PageIntent;
@@ -41,16 +42,20 @@ public void onRightClick() {
mSettingList = findViewById(R.id.setting_list);
mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
mSettingItemAdapter = new SettingItemAdapter(getContext());
- mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_log_info, false));
+ mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_log_info, LogInfoConfig.isLogInfoOpen(getContext())));
mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
@Override
public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
if (data.desc == R.string.dk_kit_log_info) {
if (on) {
- FloatPageManager.getInstance().add(new PageIntent(LogInfoFloatPage.class));
+ PageIntent intent = new PageIntent(LogInfoFloatPage.class);
+ intent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(intent);
} else {
+
FloatPageManager.getInstance().removeAll(LogInfoFloatPage.class);
}
+ LogInfoConfig.setLogInfoOpen(getContext(), on);
}
}
});
@@ -59,6 +64,6 @@ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_log_info_setting;
+ return R.layout.dk_fragment_log_info_setting;
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/AopUtils.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/AopUtils.java
new file mode 100644
index 000000000..82654cd2e
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/AopUtils.java
@@ -0,0 +1,35 @@
+package com.didichuxing.doraemonkit.kit.network.aspect;
+
+import com.didichuxing.doraemonkit.kit.network.NetworkManager;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.HttpUrlConnectionProxy;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.HttpsUrlConnectionProxy;
+import com.didichuxing.doraemonkit.kit.network.okhttp.DoraemonInterceptor;
+
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import okhttp3.OkHttpClient;
+
+/**
+ * @desc:
+ */
+public class AopUtils {
+ public static URLConnection URLOpenConnection(URLConnection connection){
+ if (!NetworkManager.isActive()) {
+ return connection;
+ }
+ if (connection instanceof HttpURLConnection) {
+ return new HttpUrlConnectionProxy((HttpURLConnection) connection);
+ } else if (connection instanceof HttpsURLConnection) {
+ return new HttpsUrlConnectionProxy((HttpsURLConnection) connection);
+ }else {
+ return connection;
+ }
+ }
+
+ public static void addInterceptor(OkHttpClient.Builder builder){
+ builder.addInterceptor(new DoraemonInterceptor());
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java
index 5de809b1b..7c0bd5c93 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java
@@ -1,28 +1,17 @@
package com.didichuxing.doraemonkit.kit.network.aspect;
-import com.didichuxing.doraemonkit.kit.network.NetworkManager;
-import com.didichuxing.doraemonkit.kit.network.httpurlconnection.RequestHandlingOutputStream;
-import com.didichuxing.doraemonkit.kit.network.httpurlconnection.URLConnectionManager;
-import com.didichuxing.doraemonkit.util.LogHelper;
-
-import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.NoAspectBoundException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.util.concurrent.ConcurrentHashMap;
+import java.net.URLConnection;
@Aspect
public class HttpUrlAspect {
private static final String TAG = "HttpUrlAspect";
private static /* synthetic */ Throwable ajc$initFailureCause;
public static /* synthetic */ HttpUrlAspect ajc$perSingletonInstance = null;
- public ConcurrentHashMap mManagerMap = new ConcurrentHashMap();
static {
try {
@@ -43,73 +32,11 @@ public static boolean hasAspect() {
return ajc$perSingletonInstance != null;
}
- @Before("call(* java.net.HttpURLConnection.connect(..))")
- public void fetchRequestInfo(JoinPoint joinPoint) {
- if (NetworkManager.isActive()) {
- LogHelper.i(TAG, "hook before call connect");
- HttpURLConnection connection = (HttpURLConnection) joinPoint.getTarget();
- if (this.mManagerMap.get(connection) == null) {
- preConnect(connection);
- }
- }
- }
-
- private URLConnectionManager preConnect(HttpURLConnection connection) {
- URLConnectionManager manager = new URLConnectionManager();
- manager.preConnect(connection);
- this.mManagerMap.put(connection, manager);
- return manager;
- }
-
- @Around("call(* java.net.HttpURLConnection.getOutputStream(..))")
- public OutputStream fetchRequestBody(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
- if (!NetworkManager.isActive()) {
- return (OutputStream) proceedingJoinPoint.proceed();
- }
- LogHelper.i(TAG, "hook method getOutputStream");
- HttpURLConnection connection = (HttpURLConnection) proceedingJoinPoint.getTarget();
- if (this.mManagerMap.get(connection) != null) {
- OutputStream outputStream = (OutputStream) proceedingJoinPoint.proceed();
- URLConnectionManager manager = this.mManagerMap.get(connection);
- if (manager != null) {
- return new RequestHandlingOutputStream(outputStream, manager);
- }
- return outputStream;
- }
- return new RequestHandlingOutputStream((OutputStream) proceedingJoinPoint.proceed(), preConnect(connection));
- }
-
- @Around("call(* java.net.HttpURLConnection.getResponseCode(..))")
- public int fetchResponseInfo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
- if (!NetworkManager.isActive()) {
- return ((Integer) proceedingJoinPoint.proceed()).intValue();
- }
- LogHelper.i(TAG, "hook after call getResponseCode");
- HttpURLConnection connection = (HttpURLConnection) proceedingJoinPoint.getTarget();
- if (this.mManagerMap.get(connection) == null) {
- preConnect(connection);
- }
- URLConnectionManager manager = this.mManagerMap.get(connection);
- manager.fetchRequestBody();
- int code = ((Integer) proceedingJoinPoint.proceed()).intValue();
- if (manager != null) {
- manager.postConnect(code);
- }
- return code;
+ @Around("call(* java.net.URL.openConnection(..))")
+ public URLConnection URLOpenConnection(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+ URLConnection connection = (URLConnection) proceedingJoinPoint.proceed();
+ return AopUtils.URLOpenConnection(connection);
}
- @Around("call(* java.net.HttpURLConnection.getInputStream(..))")
- public InputStream fetchResponseBody(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
- if (!NetworkManager.isActive()) {
- return (InputStream) proceedingJoinPoint.proceed();
- }
- LogHelper.i(TAG, "hook method getInputStream");
- InputStream inputStream = (InputStream) proceedingJoinPoint.proceed();
- HttpURLConnection connection = (HttpURLConnection) proceedingJoinPoint.getTarget();
- if (this.mManagerMap.get(connection) == null) {
- return inputStream;
- }
- return this.mManagerMap.remove(connection).interpretResponseStream(inputStream);
- }
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java
index 97e3d03ff..c4c9a04a2 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java
@@ -1,9 +1,5 @@
package com.didichuxing.doraemonkit.kit.network.aspect;
-import com.didichuxing.doraemonkit.kit.network.NetworkManager;
-import com.didichuxing.doraemonkit.kit.network.okhttp.DoraemonInterceptor;
-import com.didichuxing.doraemonkit.util.LogHelper;
-
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.NoAspectBoundException;
import org.aspectj.lang.annotation.Aspect;
@@ -38,9 +34,6 @@ public static boolean hasAspect() {
@Before("call(* okhttp3.OkHttpClient.Builder.build(..))")
public void addInterceptor(JoinPoint joinPoint) {
- if (NetworkManager.isActive()) {
- LogHelper.i(TAG, "add DoraemonInterceptor success");
- ((Builder) joinPoint.getTarget()).addInterceptor(new DoraemonInterceptor());
- }
+ AopUtils.addInterceptor((Builder) joinPoint.getTarget());
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/Request.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/Request.java
index 509791254..e9c9c46da 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/Request.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/Request.java
@@ -17,6 +17,8 @@ public class Request implements Serializable {
public String postData;
+ public String encode;
+
@Override
public String toString() {
return String.format("[%s %s %s %s]", url, method, headers.toString(), postData);
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java
index 52b60da29..0cfdde599 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/common/CommonHeaders.java
@@ -3,15 +3,12 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
-import okhttp3.internal.Util;
-import okhttp3.internal.http.HttpDate;
/**
* The header fields of a single HTTP message. Values are uninterpreted strings; use {@code Request}
@@ -45,14 +42,6 @@ public String get(String name) {
return get(namesAndValues, name);
}
- /**
- * Returns the last value corresponding to the specified field parsed as an HTTP date, or null if
- * either the field is absent or cannot be parsed as a date.
- */
- public Date getDate(String name) {
- String value = get(name);
- return value != null ? HttpDate.parse(value) : null;
- }
/** Returns the number of field values. */
public int size() {
@@ -292,7 +281,7 @@ private void checkNameAndValue(String name, String value) {
for (int i = 0, length = name.length(); i < length; i++) {
char c = name.charAt(i);
if (c <= '\u0020' || c >= '\u007f') {
- throw new IllegalArgumentException(Util.format(
+ throw new IllegalArgumentException(format(
"Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
}
}
@@ -300,7 +289,7 @@ private void checkNameAndValue(String name, String value) {
for (int i = 0, length = value.length(); i < length; i++) {
char c = value.charAt(i);
if ((c <= '\u001f' && c != '\t') || c >= '\u007f') {
- throw new IllegalArgumentException(Util.format(
+ throw new IllegalArgumentException(format(
"Unexpected char %#04x at %d in %s value: %s", (int) c, i, name, value));
}
}
@@ -320,4 +309,9 @@ public CommonHeaders build() {
return new CommonHeaders(this);
}
}
+
+ /** Returns a {@link Locale#US} formatted {@link String}. */
+ public static String format(String format, Object... args) {
+ return String.format(Locale.US, format, args);
+ }
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/CountingOutputStream.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/CountingOutputStream.java
deleted file mode 100644
index d9e530897..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/CountingOutputStream.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-package com.didichuxing.doraemonkit.kit.network.core;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-class CountingOutputStream extends FilterOutputStream {
- private long mCount;
-
- public CountingOutputStream(OutputStream out) {
- super(out);
- }
-
- public long getCount() {
- return mCount;
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- out.write(oneByte);
- mCount++;
- }
-
- @Override
- public void write(byte[] buffer) throws IOException {
- write(buffer, 0, buffer.length);
- }
-
- @Override
- public void write(byte[] buffer, int offset, int length) throws IOException {
- out.write(buffer, offset, length);
- mCount += length;
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DecompressionHelper.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DecompressionHelper.java
deleted file mode 100644
index d2858a211..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DecompressionHelper.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-package com.didichuxing.doraemonkit.kit.network.core;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class DecompressionHelper {
- static final String GZIP_ENCODING = "gzip";
- static final String DEFLATE_ENCODING = "deflate";
-
- public static InputStream teeInputWithDecompression(
- int requestId,
- InputStream availableInputStream,
- ResponseHandler responseHandler) throws IOException {
- CountingOutputStream decompressedCounter = null;
-
- return new ResponseHandlingInputStream(
- availableInputStream,
- requestId,
- decompressedCounter,
- responseHandler);
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DefaultResponseHandler.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DefaultResponseHandler.java
index c2b7b48ba..ceff4d3fc 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DefaultResponseHandler.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/DefaultResponseHandler.java
@@ -20,8 +20,6 @@ public class DefaultResponseHandler implements ResponseHandler {
private final int mRequestId;
private NetworkRecord mRecord;
- private int mBytesRead = 0;
- private int mDecodedBytesRead = -1;
public DefaultResponseHandler(NetworkInterpreter networkInterpreter, int requestId, NetworkRecord record) {
mNetworkInterpreter = networkInterpreter;
@@ -29,35 +27,13 @@ public DefaultResponseHandler(NetworkInterpreter networkInterpreter, int request
mRecord = record;
}
- @Override
- public void onRead(int numBytes) {
- mBytesRead += numBytes;
- }
-
- @Override
- public void onReadDecoded(int numBytes) {
- if (mDecodedBytesRead == -1) {
- mDecodedBytesRead = 0;
- }
- mDecodedBytesRead += numBytes;
- }
-
@Override
public void onEOF(ByteArrayOutputStream outputStream) {
- reportDataReceived();
mNetworkInterpreter.responseReadFinished(mRequestId,mRecord,outputStream);
}
@Override
public void onError(IOException e) {
- reportDataReceived();
mNetworkInterpreter.responseReadFailed(mRequestId, e.toString());
}
-
- private void reportDataReceived() {
- mNetworkInterpreter.dataReceived(
- mRequestId,
- mBytesRead,
- mDecodedBytesRead >= 0 ? mDecodedBytesRead : mBytesRead);
- }
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java
index 1cff43f8d..d4ca6b126 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/NetworkInterpreter.java
@@ -8,6 +8,7 @@
import com.didichuxing.doraemonkit.kit.network.bean.NetworkRecord;
import com.didichuxing.doraemonkit.kit.network.bean.Request;
import com.didichuxing.doraemonkit.kit.network.bean.Response;
+import com.didichuxing.doraemonkit.kit.network.stream.InputStreamProxy;
import com.didichuxing.doraemonkit.kit.network.utils.Utf8Charset;
import com.didichuxing.doraemonkit.util.LogHelper;
@@ -43,9 +44,6 @@ public void responseReadFailed(int requestId, String s) {
LogHelper.i(TAG, "[responseReadFailed] requestId: " + requestId + " error: " + s);
}
- public void dataReceived(int requestId, int bytesRead, int encodedDataLength) {
- LogHelper.i(TAG, "[dataReceived] requestId: " + requestId + " bytesRead: " + bytesRead + " encodedDataLength: " + encodedDataLength);
- }
private static class Holder {
private static NetworkInterpreter INSTANCE = new NetworkInterpreter();
@@ -60,8 +58,6 @@ public int nextRequestId() {
}
public InputStream interpretResponseStream(
- NetworkRecord record,
- int requestId,
String contentType,
@Nullable InputStream availableInputStream,
ResponseHandler responseHandler) {
@@ -77,19 +73,9 @@ public InputStream interpretResponseStream(
responseHandler.onEOF(null);
return availableInputStream;
}
- try {
- return DecompressionHelper.teeInputWithDecompression(
- requestId,
- availableInputStream,
- responseHandler);
- } catch (IOException e) {
-// CLog.writeToConsole(
-// peerManager,
-// Console.MessageLevel.ERROR,
-// Console.MessageSource.NETWORK,
-// "Error writing response body data for request #" + requestId);
- }
- return availableInputStream;
+ return new InputStreamProxy(
+ availableInputStream,
+ responseHandler);
}
@@ -106,6 +92,7 @@ private void fetchRequestInfo(NetworkRecord record, NetworkInterpreter.Inspector
requestJSON.url = request.url();
requestJSON.method = request.method();
requestJSON.headers = formatHeadersAsString(request);
+ requestJSON.encode = request.firstHeaderValue("Content-Encoding");
requestJSON.postData = readBodyAsString(request);
record.mRequest = requestJSON;
record.startTime = System.currentTimeMillis();
@@ -113,7 +100,7 @@ private void fetchRequestInfo(NetworkRecord record, NetworkInterpreter.Inspector
Log.e(TAG, requestJSON.toString());
}
- public void fetRequestBody(NetworkRecord record, NetworkInterpreter.InspectorRequest request) {
+ public void fetRequestBody(NetworkRecord record, byte[] request) {
if (record.mRequest != null) {
record.mRequest.postData = readBodyAsString(request);
record.requestLength = readBodyLength(request);
@@ -122,11 +109,11 @@ public void fetRequestBody(NetworkRecord record, NetworkInterpreter.InspectorReq
}
}
- public void fetchResponseBody(NetworkRecord record,String body){
- if (TextUtils.isEmpty(body)){
+ public void fetchResponseBody(NetworkRecord record, String body) {
+ if (TextUtils.isEmpty(body)) {
record.responseLength = 0;
record.mResponseBody = null;
- }else {
+ } else {
record.responseLength = body.getBytes().length;
record.mResponseBody = body;
}
@@ -177,11 +164,17 @@ private String readBodyAsString(
return new String(body, Utf8Charset.INSTANCE);
}
} catch (IOException | OutOfMemoryError e) {
-// CLog.writeToConsole(
-// peerManager,
-// Console.MessageLevel.WARNING,
-// Console.MessageSource.NETWORK,
-// "Could not reproduce POST body: " + e);
+ }
+ return null;
+ }
+
+ private String readBodyAsString(
+ byte[] body) {
+ try {
+ if (body != null) {
+ return new String(body, Utf8Charset.INSTANCE);
+ }
+ } catch (OutOfMemoryError e) {
}
return null;
}
@@ -194,15 +187,20 @@ private long readBodyLength(
return body.length;
}
} catch (IOException | OutOfMemoryError e) {
-// CLog.writeToConsole(
-// peerManager,
-// Console.MessageLevel.WARNING,
-// Console.MessageSource.NETWORK,
-// "Could not reproduce POST body: " + e);
}
return 0;
}
+ private long readBodyLength(
+ byte[] body) {
+ try {
+ if (body != null) {
+ return body.length;
+ }
+ } catch (OutOfMemoryError e) {
+ }
+ return 0;
+ }
private String getContentType(NetworkInterpreter.InspectorHeaders headers) {
// This may need to change in the future depending on how cumbersome header simulation
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/RequestBodyHelper.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/RequestBodyHelper.java
index d6a29d57d..8be17ea66 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/RequestBodyHelper.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/RequestBodyHelper.java
@@ -9,6 +9,9 @@
package com.didichuxing.doraemonkit.kit.network.core;
+
+import com.didichuxing.doraemonkit.kit.network.stream.GunzippingOutputStream;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -20,23 +23,21 @@
public class RequestBodyHelper {
private ByteArrayOutputStream mDeflatedOutput;
- private CountingOutputStream mDeflatingOutput;
+ private static final String GZIP_ENCODING = "gzip";
+ private static final String DEFLATE_ENCODING = "deflate";
public OutputStream createBodySink(String contentEncoding) throws IOException {
OutputStream deflatingOutput;
ByteArrayOutputStream deflatedOutput = new ByteArrayOutputStream();
- if (DecompressionHelper.GZIP_ENCODING.equals(contentEncoding)) {
+ if (GZIP_ENCODING.equals(contentEncoding)) {
deflatingOutput = GunzippingOutputStream.create(deflatedOutput);
- } else if (DecompressionHelper.DEFLATE_ENCODING.equals(contentEncoding)) {
+ } else if (DEFLATE_ENCODING.equals(contentEncoding)) {
deflatingOutput = new InflaterOutputStream(deflatedOutput);
} else {
deflatingOutput = deflatedOutput;
}
-
- mDeflatingOutput = new CountingOutputStream(deflatingOutput);
mDeflatedOutput = deflatedOutput;
-
- return mDeflatingOutput;
+ return deflatingOutput;
}
public byte[] getDisplayBody() {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandler.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandler.java
index 7c932fc50..9a7ab152e 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandler.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandler.java
@@ -13,9 +13,6 @@
import java.io.IOException;
public interface ResponseHandler {
- void onRead(int numBytes);
-
- void onReadDecoded(int numBytes);
void onEOF(ByteArrayOutputStream outputStream);
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/ByteArrayRequestEntity.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/ByteArrayRequestEntity.java
deleted file mode 100644
index 6b125c9c9..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/ByteArrayRequestEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class ByteArrayRequestEntity implements SimpleRequestEntity {
- private final byte[] mData;
-
- public ByteArrayRequestEntity(byte[] data) {
- mData = data;
- }
-
- @Override
- public void writeTo(OutputStream out) throws IOException {
- out.write(mData);
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpMonitorInterceptor.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpMonitorInterceptor.java
new file mode 100644
index 000000000..8f5602a19
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpMonitorInterceptor.java
@@ -0,0 +1,100 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
+
+import android.support.annotation.NonNull;
+import android.util.Log;
+import android.util.Pair;
+
+import com.didichuxing.doraemonkit.kit.network.NetworkManager;
+import com.didichuxing.doraemonkit.kit.network.bean.NetworkRecord;
+import com.didichuxing.doraemonkit.kit.network.core.DefaultResponseHandler;
+import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.DKInterceptor;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpRequest;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpRequestChain;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpRequestStreamChain;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpResponse;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpResponseChain;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpResponseStreamChain;
+import com.didichuxing.doraemonkit.kit.network.stream.HttpOutputStreamProxy;
+import com.didichuxing.doraemonkit.kit.network.stream.OutputStreamProxy;
+import com.didichuxing.doraemonkit.kit.network.utils.StreamUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+
+/**
+ * @desc: 监听HttpUrlConnection数据的拦截器
+ */
+public class HttpMonitorInterceptor implements DKInterceptor {
+ private static final String TAG = "HeaderParseInterceptor";
+ private final NetworkInterpreter mInterpreter;
+
+ public HttpMonitorInterceptor() {
+ mInterpreter = NetworkInterpreter.get();
+ }
+
+ @Override
+ public void intercept(@NonNull HttpRequestChain chain, @NonNull HttpRequest request) throws IOException {
+ int requestId = request.getId();
+ if (NetworkManager.get().getRecord(requestId) != null) {
+ chain.process(request);
+ return;
+ }
+ HttpURLConnection connection = request.getURLConnection();
+ ArrayList> header;
+ // connect参数不知道什么会被置为true,以防崩溃,这里直接try-catch住
+ try {
+ header = StreamUtil.convertHeaders(connection.getRequestProperties());
+ } catch (Exception e) {
+ Log.e(TAG, "get head exception", e);
+ header = new ArrayList<>();
+ }
+ URLConnectionInspectorRequest inspectorRequest = new URLConnectionInspectorRequest(
+ requestId,
+ header,
+ connection);
+ mInterpreter.createRecord(requestId, inspectorRequest);
+ chain.process(request);
+ }
+
+ @Override
+ public void intercept(@NonNull HttpResponseChain chain, @NonNull HttpResponse response) throws IOException {
+ int id = response.getId();
+ NetworkRecord record = NetworkManager.get().getRecord(id);
+ if (record == null) {
+ chain.process(response);
+ return;
+ }
+ URLConnectionInspectorResponse urlConnectionInspectorResponse = new URLConnectionInspectorResponse(
+ response.getId(),
+ response.getURLConnection(),
+ response.getStatusCode());
+ mInterpreter.fetchResponseInfo(record, urlConnectionInspectorResponse);
+ chain.process(response);
+ }
+
+ @Override
+ public void intercept(@NonNull HttpRequestStreamChain chain, @NonNull HttpRequest request) throws IOException {
+ OutputStreamProxy outputStream = new HttpOutputStreamProxy(request.getOutputStream(), request.getId(), mInterpreter);
+ request.setOutputStream(outputStream);
+ chain.process(request);
+ }
+
+ @Override
+ public void intercept(@NonNull HttpResponseStreamChain chain, @NonNull HttpResponse response) throws IOException {
+ int id = response.getId();
+ NetworkRecord record = NetworkManager.get().getRecord(id);
+ if (record == null) {
+ chain.process(response);
+ }
+ HttpURLConnection connection = response.getURLConnection();
+ InputStream responseStream = mInterpreter.interpretResponseStream(
+ connection.getHeaderField("Content-Type"),
+ response.getInputStream(),
+ new DefaultResponseHandler(mInterpreter, id, record));
+ response.setInputStream(responseStream);
+ chain.process(response);
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpUrlConnectionProxy.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpUrlConnectionProxy.java
new file mode 100644
index 000000000..8967f7f02
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpUrlConnectionProxy.java
@@ -0,0 +1,337 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
+
+import android.util.Log;
+
+import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.DKInterceptor;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpChainFacade;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpRequest;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpResponse;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @desc: UrlConnection代理类,用以解析请求
+ */
+public class HttpUrlConnectionProxy extends HttpURLConnection {
+ private final String TAG = "HttpUrlConnectionProxy";
+ private final boolean DEBUG = true;
+ private final HttpURLConnection mSourceConnection;
+ private List mInterceptors = new ArrayList<>();
+
+ private final HttpRequest mHttpRequest;
+ private final HttpResponse mHttpResponse;
+
+ private final HttpChainFacade mHttpChainFacade;
+
+ public HttpUrlConnectionProxy(HttpURLConnection con) {
+ super(con.getURL());
+ mSourceConnection = con;
+
+ mInterceptors.add(new HttpMonitorInterceptor());
+
+ NetworkInterpreter mInterpreter = NetworkInterpreter.get();
+ int requestId = mInterpreter.nextRequestId();
+ mHttpRequest = new HttpRequest(requestId, con);
+ mHttpResponse = new HttpResponse(requestId, con);
+
+ mHttpChainFacade = new HttpChainFacade(mInterceptors);
+ }
+
+ @Override
+ public void addRequestProperty(String field, String newValue) {
+ mSourceConnection.addRequestProperty(field, newValue);
+ }
+
+ @Override
+ public void disconnect() {
+ // TODO Auto-generated method stub
+ if (DEBUG) {
+ Log.d(TAG, "disconnect. ");
+ }
+ mSourceConnection.disconnect();
+ }
+
+
+ @Override
+ public boolean usingProxy() {
+ return mSourceConnection.usingProxy();
+ }
+
+ @Override
+ public void connect() throws IOException {
+ preConnect();
+ try {
+ mSourceConnection.connect();
+ } catch (IOException e) {
+ throw e;
+ }
+ }
+
+ /**
+ */
+ public void preConnect() throws IOException {
+ mHttpChainFacade.process(mHttpRequest);
+ }
+
+ public void postConnect(int statusCode) throws IOException {
+ mHttpResponse.setStatusCode(statusCode);
+ mHttpChainFacade.process(mHttpResponse);
+ }
+
+ @Override
+ public boolean getAllowUserInteraction() {
+ return mSourceConnection.getAllowUserInteraction();
+ }
+
+ @Override
+ public int getConnectTimeout() {
+ return mSourceConnection.getConnectTimeout();
+ }
+
+ @Override
+ public Object getContent() throws IOException {
+ return mSourceConnection.getContent();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Object getContent(Class[] types) throws IOException {
+ return mSourceConnection.getContent(types);
+ }
+
+ @Override
+ public String getContentEncoding() {
+ return mSourceConnection.getContentEncoding();
+ }
+
+ @Override
+ public int getContentLength() {
+ return mSourceConnection.getContentLength();
+ }
+
+ @Override
+ public String getContentType() {
+ return mSourceConnection.getContentType();
+ }
+
+ @Override
+ public long getDate() {
+ return mSourceConnection.getDate();
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return mSourceConnection.getErrorStream();
+ }
+
+ @Override
+ public long getHeaderFieldDate(String field, long defaultValue) {
+ return mSourceConnection.getHeaderFieldDate(field, defaultValue);
+ }
+
+ @Override
+ public boolean getInstanceFollowRedirects() {
+ return mSourceConnection.getInstanceFollowRedirects();
+ }
+
+ @Override
+ public java.security.Permission getPermission() throws IOException {
+ return mSourceConnection.getPermission();
+ }
+
+ @Override
+ public String getRequestMethod() {
+ return mSourceConnection.getRequestMethod();
+ }
+
+ @Override
+ public int getResponseCode() throws IOException {
+ preConnect();
+ int code = mSourceConnection.getResponseCode();
+ postConnect(code);
+ return code;
+ }
+
+ @Override
+ public String getResponseMessage() throws IOException {
+ return mSourceConnection.getResponseMessage();
+ }
+
+ @Override
+ public void setChunkedStreamingMode(int chunkLength) {
+ mSourceConnection.setChunkedStreamingMode(chunkLength);
+ }
+
+ @Override
+ public void setFixedLengthStreamingMode(int contentLength) {
+ mSourceConnection.setFixedLengthStreamingMode(contentLength);
+ }
+
+ @Override
+ public void setInstanceFollowRedirects(boolean followRedirects) {
+ mSourceConnection.setInstanceFollowRedirects(followRedirects);
+ }
+
+ @Override
+ public void setRequestMethod(String method) throws ProtocolException {
+ mSourceConnection.setRequestMethod(method);
+ }
+
+ @Override
+ public boolean getDefaultUseCaches() {
+ return mSourceConnection.getDefaultUseCaches();
+ }
+
+ @Override
+ public boolean getDoInput() {
+ return mSourceConnection.getDoInput();
+ }
+
+ @Override
+ public boolean getDoOutput() {
+ return mSourceConnection.getDoOutput();
+ }
+
+ @Override
+ public long getExpiration() {
+ return mSourceConnection.getExpiration();
+ }
+
+ @Override
+ public String getHeaderField(int pos) {
+ return mSourceConnection.getHeaderField(pos);
+ }
+
+ @Override
+ public String getHeaderField(String key) {
+ return mSourceConnection.getHeaderField(key);
+ }
+
+ @Override
+ public int getHeaderFieldInt(String field, int defaultValue) {
+ return mSourceConnection.getHeaderFieldInt(field, defaultValue);
+ }
+
+ @Override
+ public String getHeaderFieldKey(int paramInt) {
+ return mSourceConnection.getHeaderFieldKey(paramInt);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Override
+ public Map> getHeaderFields() {
+ return mSourceConnection.getHeaderFields();
+ }
+
+ @Override
+ public long getIfModifiedSince() {
+ return mSourceConnection.getIfModifiedSince();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ mHttpResponse.setInputStream(mSourceConnection.getInputStream());
+ mHttpChainFacade.processStream(mHttpResponse);
+ return mHttpResponse.getInputStream();
+ }
+
+ @Override
+ public long getLastModified() {
+ return mSourceConnection.getLastModified();
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ mHttpRequest.setOutputStream(mSourceConnection.getOutputStream());
+ mHttpChainFacade.processStream(mHttpRequest);
+ return mHttpRequest.getOutputStream();
+ }
+
+ @Override
+ public int getReadTimeout() {
+ return mSourceConnection.getReadTimeout();
+ }
+
+ @Override
+ public Map> getRequestProperties() {
+ return mSourceConnection.getRequestProperties();
+ }
+
+ @Override
+ public String getRequestProperty(String field) {
+ return mSourceConnection.getRequestProperty(field);
+ }
+
+ @Override
+ public URL getURL() {
+ return mSourceConnection.getURL();
+ }
+
+ @Override
+ public boolean getUseCaches() {
+ return mSourceConnection.getUseCaches();
+ }
+
+ @Override
+ public void setAllowUserInteraction(boolean newValue) {
+ mSourceConnection.setAllowUserInteraction(newValue);
+ }
+
+ @Override
+ public void setConnectTimeout(int timeout) {
+ mSourceConnection.setConnectTimeout(timeout);
+ }
+
+ @Override
+ public void setDefaultUseCaches(boolean newValue) {
+ mSourceConnection.setDefaultUseCaches(newValue);
+ }
+
+ @Override
+ public void setDoInput(boolean newValue) {
+ mSourceConnection.setDoInput(newValue);
+ }
+
+ @Override
+ public void setDoOutput(boolean newValue) {
+ mSourceConnection.setDoOutput(newValue);
+ }
+
+ @Override
+ public void setIfModifiedSince(long newValue) {
+ mSourceConnection.setIfModifiedSince(newValue);
+ }
+
+ @Override
+ public void setReadTimeout(int timeout) {
+ mSourceConnection.setReadTimeout(timeout);
+ }
+
+ @Override
+ public void setRequestProperty(String field, String newValue) {
+ mSourceConnection.setRequestProperty(field, newValue);
+ }
+
+ @Override
+ public void setUseCaches(boolean newValue) {
+ mSourceConnection.setUseCaches(newValue);
+ }
+
+ @Override
+ public String toString() {
+ if (mSourceConnection == null) {
+ return "this connection object is null";
+ } else {
+ return mSourceConnection.toString();
+ }
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpsUrlConnectionProxy.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpsUrlConnectionProxy.java
new file mode 100644
index 000000000..e7b9627ee
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/HttpsUrlConnectionProxy.java
@@ -0,0 +1,357 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
+
+import android.util.Log;
+
+import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.DKInterceptor;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpChainFacade;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpRequest;
+import com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor.HttpResponse;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+/**
+ * @desc: UrlConnection代理类,用以解析请求
+ */
+public class HttpsUrlConnectionProxy extends HttpsURLConnection {
+ private final String TAG = "HttpUrlConnectionProxy";
+ private final boolean DEBUG = true;
+ private final HttpsURLConnection mSourceConnection;
+ private List mInterceptors = new ArrayList<>();
+
+ private final HttpRequest mHttpRequest;
+ private final HttpResponse mHttpResponse;
+
+ private final HttpChainFacade mHttpChainFacade;
+
+ public HttpsUrlConnectionProxy(HttpsURLConnection con) {
+ super(con.getURL());
+ mSourceConnection = con;
+
+ mInterceptors.add(new HttpMonitorInterceptor());
+
+ NetworkInterpreter mInterpreter = NetworkInterpreter.get();
+ int requestId = mInterpreter.nextRequestId();
+ mHttpRequest = new HttpRequest(requestId, con);
+ mHttpResponse = new HttpResponse(requestId, con);
+
+ mHttpChainFacade = new HttpChainFacade(mInterceptors);
+ }
+
+ @Override
+ public String getCipherSuite() {
+ return mSourceConnection.getCipherSuite();
+ }
+
+ @Override
+ public Certificate[] getLocalCertificates() {
+ return mSourceConnection.getLocalCertificates();
+ }
+
+ @Override
+ public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException {
+ return mSourceConnection.getServerCertificates();
+ }
+
+ @Override
+ public void addRequestProperty(String field, String newValue) {
+ mSourceConnection.addRequestProperty(field, newValue);
+ }
+
+ @Override
+ public void disconnect() {
+ // TODO Auto-generated method stub
+ if (DEBUG) {
+ Log.d(TAG, "disconnect. ");
+ }
+ mSourceConnection.disconnect();
+ }
+
+
+ @Override
+ public boolean usingProxy() {
+ return mSourceConnection.usingProxy();
+ }
+
+ @Override
+ public void connect() throws IOException {
+ preConnect();
+ try {
+ mSourceConnection.connect();
+ } catch (IOException e) {
+ throw e;
+ }
+ }
+
+ /**
+ */
+ public void preConnect() throws IOException {
+ mHttpChainFacade.process(mHttpRequest);
+ }
+
+ public void postConnect(int statusCode) throws IOException {
+ mHttpResponse.setStatusCode(statusCode);
+ mHttpChainFacade.process(mHttpResponse);
+ }
+
+
+ @Override
+ public boolean getAllowUserInteraction() {
+ return mSourceConnection.getAllowUserInteraction();
+ }
+
+ @Override
+ public int getConnectTimeout() {
+ return mSourceConnection.getConnectTimeout();
+ }
+
+ @Override
+ public Object getContent() throws IOException {
+ return mSourceConnection.getContent();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Object getContent(Class[] types) throws IOException {
+ return mSourceConnection.getContent(types);
+ }
+
+ @Override
+ public String getContentEncoding() {
+ return mSourceConnection.getContentEncoding();
+ }
+
+ @Override
+ public int getContentLength() {
+ return mSourceConnection.getContentLength();
+ }
+
+ @Override
+ public String getContentType() {
+ return mSourceConnection.getContentType();
+ }
+
+ @Override
+ public long getDate() {
+ return mSourceConnection.getDate();
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return mSourceConnection.getErrorStream();
+ }
+
+ @Override
+ public long getHeaderFieldDate(String field, long defaultValue) {
+ return mSourceConnection.getHeaderFieldDate(field, defaultValue);
+ }
+
+ @Override
+ public boolean getInstanceFollowRedirects() {
+ return mSourceConnection.getInstanceFollowRedirects();
+ }
+
+ @Override
+ public java.security.Permission getPermission() throws IOException {
+ return mSourceConnection.getPermission();
+ }
+
+ @Override
+ public String getRequestMethod() {
+ return mSourceConnection.getRequestMethod();
+ }
+
+ @Override
+ public int getResponseCode() throws IOException {
+ preConnect();
+ int code = mSourceConnection.getResponseCode();
+ postConnect(code);
+ return code;
+ }
+
+ @Override
+ public String getResponseMessage() throws IOException {
+ return mSourceConnection.getResponseMessage();
+ }
+
+ @Override
+ public void setChunkedStreamingMode(int chunkLength) {
+ mSourceConnection.setChunkedStreamingMode(chunkLength);
+ }
+
+ @Override
+ public void setFixedLengthStreamingMode(int contentLength) {
+ mSourceConnection.setFixedLengthStreamingMode(contentLength);
+ }
+
+ @Override
+ public void setInstanceFollowRedirects(boolean followRedirects) {
+ mSourceConnection.setInstanceFollowRedirects(followRedirects);
+ }
+
+ @Override
+ public void setRequestMethod(String method) throws ProtocolException {
+ mSourceConnection.setRequestMethod(method);
+ }
+
+ @Override
+ public boolean getDefaultUseCaches() {
+ return mSourceConnection.getDefaultUseCaches();
+ }
+
+ @Override
+ public boolean getDoInput() {
+ return mSourceConnection.getDoInput();
+ }
+
+ @Override
+ public boolean getDoOutput() {
+ return mSourceConnection.getDoOutput();
+ }
+
+ @Override
+ public long getExpiration() {
+ return mSourceConnection.getExpiration();
+ }
+
+ @Override
+ public String getHeaderField(int pos) {
+ return mSourceConnection.getHeaderField(pos);
+ }
+
+ @Override
+ public String getHeaderField(String key) {
+ return mSourceConnection.getHeaderField(key);
+ }
+
+ @Override
+ public int getHeaderFieldInt(String field, int defaultValue) {
+ return mSourceConnection.getHeaderFieldInt(field, defaultValue);
+ }
+
+ @Override
+ public String getHeaderFieldKey(int paramInt) {
+ return mSourceConnection.getHeaderFieldKey(paramInt);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Override
+ public Map> getHeaderFields() {
+ return mSourceConnection.getHeaderFields();
+ }
+
+ @Override
+ public long getIfModifiedSince() {
+ return mSourceConnection.getIfModifiedSince();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ mHttpResponse.setInputStream(mSourceConnection.getInputStream());
+ mHttpChainFacade.processStream(mHttpResponse);
+ return mHttpResponse.getInputStream();
+ }
+
+ @Override
+ public long getLastModified() {
+ return mSourceConnection.getLastModified();
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ mHttpRequest.setOutputStream(mSourceConnection.getOutputStream());
+ mHttpChainFacade.processStream(mHttpRequest);
+ return mHttpRequest.getOutputStream();
+ }
+
+ @Override
+ public int getReadTimeout() {
+ return mSourceConnection.getReadTimeout();
+ }
+
+ @Override
+ public Map> getRequestProperties() {
+ return mSourceConnection.getRequestProperties();
+ }
+
+ @Override
+ public String getRequestProperty(String field) {
+ return mSourceConnection.getRequestProperty(field);
+ }
+
+ @Override
+ public URL getURL() {
+ return mSourceConnection.getURL();
+ }
+
+ @Override
+ public boolean getUseCaches() {
+ return mSourceConnection.getUseCaches();
+ }
+
+ @Override
+ public void setAllowUserInteraction(boolean newValue) {
+ mSourceConnection.setAllowUserInteraction(newValue);
+ }
+
+ @Override
+ public void setConnectTimeout(int timeout) {
+ mSourceConnection.setConnectTimeout(timeout);
+ }
+
+ @Override
+ public void setDefaultUseCaches(boolean newValue) {
+ mSourceConnection.setDefaultUseCaches(newValue);
+ }
+
+ @Override
+ public void setDoInput(boolean newValue) {
+ mSourceConnection.setDoInput(newValue);
+ }
+
+ @Override
+ public void setDoOutput(boolean newValue) {
+ mSourceConnection.setDoOutput(newValue);
+ }
+
+ @Override
+ public void setIfModifiedSince(long newValue) {
+ mSourceConnection.setIfModifiedSince(newValue);
+ }
+
+ @Override
+ public void setReadTimeout(int timeout) {
+ mSourceConnection.setReadTimeout(timeout);
+ }
+
+ @Override
+ public void setRequestProperty(String field, String newValue) {
+ mSourceConnection.setRequestProperty(field, newValue);
+ }
+
+ @Override
+ public void setUseCaches(boolean newValue) {
+ mSourceConnection.setUseCaches(newValue);
+ }
+
+ @Override
+ public String toString() {
+ if (mSourceConnection == null) {
+ return "this connection object is null";
+ } else {
+ return mSourceConnection.toString();
+ }
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/RequestHandlingOutputStream.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/RequestHandlingOutputStream.java
deleted file mode 100644
index b2d79109e..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/RequestHandlingOutputStream.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
-
-import android.support.annotation.NonNull;
-
-import com.didichuxing.doraemonkit.util.LogHelper;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.ref.WeakReference;
-
-/**
- * @desc: OutputStream的包装类,在写入时记录写入的内容
- */
-public class RequestHandlingOutputStream extends FilterOutputStream {
- private final WeakReference mManager;
-
- public RequestHandlingOutputStream(@NonNull OutputStream out, URLConnectionManager manager) {
- super(out);
- mManager = new WeakReference<>(manager);
- }
-
- @Override
- public void flush() throws IOException {
- super.flush();
- }
-
- @Override
- public void write(@NonNull byte[] b, int off, int len) throws IOException {
- LogHelper.i("RequestHand","write()");
- if (mManager.get() != null) {
- mManager.get().mOutputStream.write(b, off, len);
- }
- super.write(b, off, len);
- }
-
-
- @Override
- public void close() throws IOException {
- super.close();
- mManager.clear();
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/SimpleRequestEntity.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/SimpleRequestEntity.java
deleted file mode 100644
index 5feb028b7..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/SimpleRequestEntity.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public interface SimpleRequestEntity {
- void writeTo(OutputStream out) throws IOException;
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionInspectorRequest.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionInspectorRequest.java
index 6565e7380..1cfd07c99 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionInspectorRequest.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionInspectorRequest.java
@@ -13,10 +13,8 @@
import android.util.Pair;
import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
-import com.didichuxing.doraemonkit.kit.network.core.RequestBodyHelper;
import java.io.IOException;
-import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
@@ -25,28 +23,19 @@ public class URLConnectionInspectorRequest
extends URLConnectionInspectorHeaders
implements NetworkInterpreter.InspectorRequest {
private final int mRequestId;
- private SimpleRequestEntity mRequestEntity;
- private final RequestBodyHelper mRequestBodyHelper;
private final String mUrl;
private final String mMethod;
- private final HttpURLConnection mConnection;
public URLConnectionInspectorRequest(
int requestId,
ArrayList> header,
- HttpURLConnection configuredRequest,
- RequestBodyHelper requestBodyHelper) {
+ HttpURLConnection configuredRequest) {
super(header);
mRequestId = requestId;
- mRequestBodyHelper = requestBodyHelper;
- mConnection = configuredRequest;
mUrl = configuredRequest.getURL().toString();
mMethod = configuredRequest.getRequestMethod();
}
- public void setRequestEntity(SimpleRequestEntity entity) {
- mRequestEntity = entity;
- }
@Override
public int id() {
@@ -66,16 +55,6 @@ public String method() {
@Nullable
@Override
public byte[] body() throws IOException {
- if (mRequestEntity != null) {
- OutputStream out = mRequestBodyHelper.createBodySink(firstHeaderValue("Content-Encoding"));
- try {
- mRequestEntity.writeTo(out);
- } finally {
- out.close();
- }
- return mRequestBodyHelper.getDisplayBody();
- } else {
return null;
- }
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionManager.java
deleted file mode 100644
index d42e90a53..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/URLConnectionManager.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
-
-package com.didichuxing.doraemonkit.kit.network.httpurlconnection;
-
-import android.support.annotation.Nullable;
-import android.util.Log;
-import android.util.Pair;
-
-import com.didichuxing.doraemonkit.kit.network.bean.NetworkRecord;
-import com.didichuxing.doraemonkit.kit.network.core.DefaultResponseHandler;
-import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
-import com.didichuxing.doraemonkit.kit.network.core.RequestBodyHelper;
-import com.didichuxing.doraemonkit.kit.network.utils.StreamUtil;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.util.ArrayList;
-
-
-public class URLConnectionManager {
- public static final String TAG = "URLConnectionManager";
- private final NetworkInterpreter mInterpreter = NetworkInterpreter.get();
- private final int mRequestId;
- private NetworkRecord mRecord;
- private HttpURLConnection mConnection;
- @Nullable
- private URLConnectionInspectorRequest mInspectorRequest;
- @Nullable
- private RequestBodyHelper mRequestBodyHelper;
- public ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();
-
- public URLConnectionManager() {
- mRequestId = mInterpreter.nextRequestId();
- }
-
-
- /**
- */
- public void preConnect(HttpURLConnection connection) {
- throwIfConnection();
- mConnection = connection;
- mRequestBodyHelper = new RequestBodyHelper();
- ArrayList> header;
- // connect参数不知道什么会被置为true,以防崩溃,这里直接try-catch住
- try {
- header = StreamUtil.convertHeaders(connection.getRequestProperties());
- } catch (Exception e) {
- Log.e(TAG, "get head exception", e);
- header = new ArrayList<>();
- }
- mInspectorRequest = new URLConnectionInspectorRequest(
- getStethoRequestId(),
- header,
- connection,
- mRequestBodyHelper);
- mRecord = mInterpreter.createRecord(mRequestId, mInspectorRequest);
- }
-
-
- public void postConnect(int statusCode) throws IOException {
- throwIfNoConnection();
- URLConnectionInspectorResponse response = new URLConnectionInspectorResponse(
- getStethoRequestId(),
- mConnection,
- statusCode);
- mInterpreter.fetchResponseInfo(mRecord, response);
-
- }
-
- public void fetchRequestBody() {
- if (mInspectorRequest != null && mRecord != null) {
- SimpleRequestEntity entity = new ByteArrayRequestEntity(mOutputStream.toByteArray());
- mInspectorRequest.setRequestEntity(entity);
- mInterpreter.fetRequestBody(mRecord, mInspectorRequest);
- }
- }
-
- public void httpExchangeFailed(IOException ex) {
- throwIfNoConnection();
- mInterpreter.httpExchangeFailed(getStethoRequestId(), ex.toString());
- }
-
- public InputStream interpretResponseStream(@Nullable InputStream responseStream) {
- throwIfNoConnection();
- // Note that Content-Encoding is stripped out by HttpURLConnection on modern versions of
- // Android (fun fact, it's powered by okhttp) when decompression is handled transparently.
- // When this occurs, we will not be able to report the compressed size properly. Callers,
- // however, can disable this behaviour which will once again give us access to the raw
- // Content-Encoding so that we can handle it properly.
- responseStream = mInterpreter.interpretResponseStream(
- mRecord,
- mRequestId,
- mConnection.getHeaderField("Content-Type"),
- responseStream,
- new DefaultResponseHandler(mInterpreter, getStethoRequestId(), mRecord));
- return responseStream;
- }
-
-
- private void throwIfNoConnection() {
- if (mConnection == null) {
- throw new IllegalStateException("Must call preConnect");
- }
- }
-
- private void throwIfConnection() {
- if (mConnection != null) {
- throw new IllegalStateException("Must not call preConnect twice");
- }
- }
-
- public NetworkInterpreter getInterpreter() {
- return mInterpreter;
- }
-
- public int getStethoRequestId() {
- return mRequestId;
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/DKInterceptor.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/DKInterceptor.java
new file mode 100644
index 000000000..b0df837d5
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/DKInterceptor.java
@@ -0,0 +1,41 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import android.support.annotation.NonNull;
+
+import java.io.IOException;
+
+/**
+ */
+public interface DKInterceptor {
+ /**
+ * 拦截请求,处理header、method之类的信息
+ * @param chain
+ * @param request
+ * @throws IOException
+ */
+ void intercept(@NonNull HttpRequestChain chain, @NonNull T request) throws IOException;
+ /**
+ * 拦截响应,处理header、statusCode之类的信息
+ * @param chain
+ * @param response
+ * @throws IOException
+ */
+ void intercept(@NonNull HttpResponseChain chain, @NonNull S response) throws IOException;
+
+ /**
+ * 拦截请求流,用以对post body做处理
+ * @param chain
+ * @param request
+ * @throws IOException
+ */
+ void intercept(@NonNull HttpRequestStreamChain chain, @NonNull T request) throws IOException;
+
+ /**
+ * 拦截响应流,用以对返回值做处理
+ * @param chain
+ * @param response
+ * @throws IOException
+ */
+ void intercept(@NonNull HttpResponseStreamChain chain, @NonNull S response) throws IOException;
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpChainFacade.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpChainFacade.java
new file mode 100644
index 000000000..2211620cf
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpChainFacade.java
@@ -0,0 +1,39 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @date: 2019/3/14
+ * @desc: 对几个处理链的包装
+ */
+public class HttpChainFacade {
+ private final HttpRequestChain mHttpRequestChain;
+ private final HttpResponseChain mHttpResponseChain;
+ private final HttpRequestStreamChain mHttpRequestStreamChain;
+ private final HttpResponseStreamChain mHttpResponseStreamChain;
+
+ public HttpChainFacade(List interceptors) {
+ mHttpRequestChain = new HttpRequestChain(interceptors);
+ mHttpResponseChain = new HttpResponseChain(interceptors);
+ mHttpRequestStreamChain = new HttpRequestStreamChain(interceptors);
+ mHttpResponseStreamChain = new HttpResponseStreamChain(interceptors);
+ }
+
+ public void process(HttpRequest request) throws IOException {
+ mHttpRequestChain.process(request);
+ }
+
+ public void process(HttpResponse response) throws IOException {
+ mHttpResponseChain.process(response);
+ }
+
+ public void processStream(HttpRequest request) throws IOException {
+ mHttpRequestStreamChain.process(request);
+ }
+
+ public void processStream(HttpResponse response) throws IOException {
+ mHttpResponseStreamChain.process(response);
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequest.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequest.java
new file mode 100644
index 000000000..0bb7c9e9b
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequest.java
@@ -0,0 +1,35 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+
+/**
+ * @date: 2019/3/12
+ * @desc: 请求结构体
+ */
+public class HttpRequest {
+ private final int mId;
+ private final HttpURLConnection mURLConnection;
+ private OutputStream mOutputStream;
+
+ public HttpRequest(int id, HttpURLConnection urlConnection) {
+ mURLConnection = urlConnection;
+ mId = id;
+ }
+
+ public HttpURLConnection getURLConnection() {
+ return mURLConnection;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public OutputStream getOutputStream() {
+ return mOutputStream;
+ }
+
+ public void setOutputStream(OutputStream outputStream) {
+ mOutputStream = outputStream;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequestChain.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequestChain.java
new file mode 100644
index 000000000..d58753130
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequestChain.java
@@ -0,0 +1,30 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 请求处理链
+ */
+public class HttpRequestChain extends InterceptorChain {
+
+
+ @Override
+ protected void processNext(HttpRequest source, List interceptors, int index) throws IOException {
+ DKInterceptor interceptor = interceptors.get(index);
+ if (interceptor != null) {
+ index++;
+ interceptor.intercept(this, source);
+ }
+ }
+
+ public HttpRequestChain(List interceptors) {
+ this(interceptors, 0);
+ }
+
+ public HttpRequestChain(List interceptors,
+ int index) {
+ super(interceptors, index);
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequestStreamChain.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequestStreamChain.java
new file mode 100644
index 000000000..c3319c637
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpRequestStreamChain.java
@@ -0,0 +1,30 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 请求body处理链
+ */
+public class HttpRequestStreamChain extends InterceptorChain {
+
+
+ @Override
+ protected void processNext(HttpRequest source, List interceptors, int index) throws IOException {
+ DKInterceptor interceptor = interceptors.get(index);
+ if (interceptor != null) {
+ index++;
+ interceptor.intercept(this, source);
+ }
+ }
+
+ public HttpRequestStreamChain(List interceptors) {
+ this(interceptors, 0);
+ }
+
+ public HttpRequestStreamChain(List interceptors,
+ int index) {
+ super(interceptors, index);
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponse.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponse.java
new file mode 100644
index 000000000..c805ed7be
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponse.java
@@ -0,0 +1,44 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+
+/**
+ * @date: 2019/3/12
+ * @desc: 响应体
+ */
+public class HttpResponse {
+ private final int mId;
+ private final HttpURLConnection mURLConnection;
+ private int mStatusCode;
+ private InputStream mInputStream;
+
+ public HttpResponse(int id, HttpURLConnection urlConnection) {
+ mURLConnection = urlConnection;
+ mId = id;
+ }
+
+ public HttpURLConnection getURLConnection() {
+ return mURLConnection;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ mStatusCode = statusCode;
+ }
+
+ public InputStream getInputStream() {
+ return mInputStream;
+ }
+
+ public void setInputStream(InputStream inputStream) {
+ mInputStream = inputStream;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponseChain.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponseChain.java
new file mode 100644
index 000000000..cf7d2ec73
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponseChain.java
@@ -0,0 +1,30 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @date: 2019/3/11
+ * @desc: 响应处理链,不包含响应body
+ */
+public class HttpResponseChain extends InterceptorChain {
+
+ public HttpResponseChain(List interceptors) {
+ super(interceptors);
+ }
+
+ public HttpResponseChain(List interceptors, int index) {
+ super(interceptors, index);
+ }
+
+ @Override
+ protected void processNext(HttpResponse response, List interceptors,
+ int index) throws IOException {
+ DKInterceptor interceptor = interceptors.get(index);
+ if (interceptor != null) {
+ index++;
+ interceptor.intercept(this, response);
+ }
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponseStreamChain.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponseStreamChain.java
new file mode 100644
index 000000000..6653f3088
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/HttpResponseStreamChain.java
@@ -0,0 +1,30 @@
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @date: 2019/3/11
+ * @desc: 响应body处理链
+ */
+public class HttpResponseStreamChain extends InterceptorChain {
+
+ public HttpResponseStreamChain(List interceptors) {
+ super(interceptors);
+ }
+
+ public HttpResponseStreamChain(List interceptors, int index) {
+ super(interceptors, index);
+ }
+
+ @Override
+ protected void processNext(HttpResponse response, List interceptors,
+ int index) throws IOException {
+ DKInterceptor interceptor = interceptors.get(index);
+ if (interceptor != null) {
+ index++;
+ interceptor.intercept(this, response);
+ }
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/InterceptorChain.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/InterceptorChain.java
new file mode 100644
index 000000000..2ffeb613e
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/httpurlconnection/interceptor/InterceptorChain.java
@@ -0,0 +1,35 @@
+
+package com.didichuxing.doraemonkit.kit.network.httpurlconnection.interceptor;
+
+import java.io.IOException;
+import java.util.List;
+
+public abstract class InterceptorChain {
+ protected List mInterceptors;
+ protected int mIndex;
+
+ protected abstract void processNext(T buffer, List interceptors, int index)
+ throws IOException;
+
+ public InterceptorChain(List interceptors) {
+ this(interceptors, 0);
+ }
+
+ public InterceptorChain(List interceptors, int index) {
+ this.mInterceptors = interceptors;
+ this.mIndex = index;
+ }
+
+ public void processFinal(T source) throws IOException {
+// mSource.process(buffer);
+ }
+
+ public void process(T source) throws IOException {
+ if (mIndex >= mInterceptors.size()) {
+ processFinal(source);
+ } else {
+ processNext(source, mInterceptors, mIndex++);
+ }
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/okhttp/DoraemonInterceptor.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/okhttp/DoraemonInterceptor.java
index e1b7daf94..7ea837c8b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/okhttp/DoraemonInterceptor.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/okhttp/DoraemonInterceptor.java
@@ -70,8 +70,6 @@ public Response intercept(Chain chain) throws IOException {
}
responseStream = mNetworkInterpreter.interpretResponseStream(
- record,
- requestId,
contentType != null ? contentType.toString() : null,
responseStream,
new DefaultResponseHandler(mNetworkInterpreter, requestId, record));
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/GunzippingOutputStream.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/GunzippingOutputStream.java
similarity index 95%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/GunzippingOutputStream.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/GunzippingOutputStream.java
index 4f232965f..77d8e106b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/GunzippingOutputStream.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/GunzippingOutputStream.java
@@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-package com.didichuxing.doraemonkit.kit.network.core;
+package com.didichuxing.doraemonkit.kit.network.stream;
import com.didichuxing.doraemonkit.kit.network.utils.ExceptionUtil;
import com.didichuxing.doraemonkit.kit.network.utils.StreamUtil;
@@ -26,7 +26,7 @@
import java.util.zip.GZIPInputStream;
-class GunzippingOutputStream extends FilterOutputStream {
+public class GunzippingOutputStream extends FilterOutputStream {
private final Future mCopyFuture;
private static final ExecutorService sExecutor = Executors.newCachedThreadPool();
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/HttpOutputStreamProxy.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/HttpOutputStreamProxy.java
new file mode 100644
index 000000000..eaa9de044
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/HttpOutputStreamProxy.java
@@ -0,0 +1,42 @@
+package com.didichuxing.doraemonkit.kit.network.stream;
+
+import com.didichuxing.doraemonkit.kit.network.NetworkManager;
+import com.didichuxing.doraemonkit.kit.network.bean.NetworkRecord;
+import com.didichuxing.doraemonkit.kit.network.core.NetworkInterpreter;
+import com.didichuxing.doraemonkit.kit.network.core.RequestBodyHelper;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author: linjizong
+ * @date: 2019/3/14
+ * @desc:
+ */
+public class HttpOutputStreamProxy extends OutputStreamProxy {
+ private final int mRequestId;
+ private final NetworkInterpreter mInterpreter;
+
+ public HttpOutputStreamProxy(OutputStream out,int requestId, NetworkInterpreter interpreter) {
+ super(out);
+ mRequestId = requestId;
+ mInterpreter = interpreter;
+ }
+
+ @Override
+ protected void onStreamComplete() throws IOException {
+ NetworkRecord record = NetworkManager.get().getRecord(mRequestId);
+ if (record != null && record.mRequest != null) {
+ RequestBodyHelper requestBodyHelper = new RequestBodyHelper();
+ try {
+ OutputStream out = requestBodyHelper.createBodySink(record.mRequest.encode);
+ mOutputStream.writeTo(out);
+ } finally {
+ out.close();
+ }
+ byte[] body = requestBodyHelper.getDisplayBody();
+ mInterpreter.fetRequestBody(record, body);
+ }
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandlingInputStream.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/InputStreamProxy.java
similarity index 64%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandlingInputStream.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/InputStreamProxy.java
index cede6b001..9ba38e395 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/core/ResponseHandlingInputStream.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/InputStreamProxy.java
@@ -7,49 +7,37 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-package com.didichuxing.doraemonkit.kit.network.core;
+package com.didichuxing.doraemonkit.kit.network.stream;
+
+import com.didichuxing.doraemonkit.kit.network.core.ResponseHandler;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-public final class ResponseHandlingInputStream extends FilterInputStream {
+public final class InputStreamProxy extends FilterInputStream {
public static final String TAG = "ResponseHandlingInputStream";
private static final int BUFFER_SIZE = 1024;
- private final int mRequestId;
private final ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();
- private final CountingOutputStream mDecompressedCounter;
private final ResponseHandler mResponseHandler;
private boolean mClosed;
- private boolean mEofSeen;
-
private byte[] mSkipBuffer;
- private long mLastDecompressedCount = 0;
-
/**
* @param inputStream
- * @param requestId the requestId to use when we call the
- * @param decompressedCounter Optional decompressing counting output stream which
- * can be queried after each write to determine the number of decompressed bytes
- * yielded. Used to implement {@link ResponseHandler#onReadDecoded(int)}.
* @param responseHandler Special interface to intercept read events before they are sent
* to peers via methods.
*/
- public ResponseHandlingInputStream(
+ public InputStreamProxy(
InputStream inputStream,
- int requestId,
- CountingOutputStream decompressedCounter,
ResponseHandler responseHandler) {
super(inputStream);
- mRequestId = requestId;
- mDecompressedCounter = decompressedCounter;
mResponseHandler = responseHandler;
mClosed = false;
}
@@ -58,7 +46,6 @@ private synchronized int checkEOF(int n) {
if (n == -1) {
mResponseHandler.onEOF(mOutputStream);
closeOutputStreamQuietly();
- mEofSeen = true;
}
return n;
}
@@ -68,7 +55,6 @@ public int read() throws IOException {
try {
int result = checkEOF(in.read());
if (result != -1) {
- mResponseHandler.onRead(1);
writeToOutputStream(result);
}
return result;
@@ -87,7 +73,6 @@ public int read(byte[] b, int off, int len) throws IOException {
try {
int result = checkEOF(in.read(b, off, len));
if (result != -1) {
- mResponseHandler.onRead(result);
writeToOutputStream(b, off, result);
}
return result;
@@ -138,34 +123,14 @@ public void reset() throws IOException {
@Override
public void close() throws IOException {
- try {
- long bytesRead = 0;
- if (!mEofSeen) {
- byte[] buffer = new byte[BUFFER_SIZE];
- int count;
- while ((count = this.read(buffer)) != -1) {
- bytesRead += count;
- }
- }
- if (bytesRead > 0) {
-// CLog.writeToConsole(
-// mNetworkPeerManager,
-// Console.MessageLevel.ERROR,
-// Console.MessageSource.NETWORK,
-// "There were " + String.valueOf(bytesRead) + " bytes that were not consumed while "
-// + "processing request " + mRequestId);
- }
- } finally {
- super.close();
- closeOutputStreamQuietly();
- }
+ super.close();
+ closeOutputStreamQuietly();
}
private synchronized void closeOutputStreamQuietly() {
if (!mClosed) {
try {
mOutputStream.close();
- reportDecodedSizeIfApplicable();
} catch (IOException e) {
} finally {
mClosed = true;
@@ -178,21 +143,11 @@ private IOException handleIOException(IOException ex) {
return ex;
}
- private void reportDecodedSizeIfApplicable() {
- if (mDecompressedCounter != null) {
- long currentCount = mDecompressedCounter.getCount();
- int delta = (int) (currentCount - mLastDecompressedCount);
- mResponseHandler.onReadDecoded(delta);
- mLastDecompressedCount = currentCount;
- }
- }
-
private synchronized void writeToOutputStream(int oneByte) {
if (mClosed) {
return;
}
mOutputStream.write(oneByte);
- reportDecodedSizeIfApplicable();
}
private synchronized void writeToOutputStream(byte[] b, int offset, int count) {
@@ -201,7 +156,6 @@ private synchronized void writeToOutputStream(byte[] b, int offset, int count) {
}
mOutputStream.write(b, offset, count);
- reportDecodedSizeIfApplicable();
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/OutputStreamProxy.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/OutputStreamProxy.java
new file mode 100644
index 000000000..c5abeac2d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/stream/OutputStreamProxy.java
@@ -0,0 +1,40 @@
+package com.didichuxing.doraemonkit.kit.network.stream;
+
+import android.support.annotation.NonNull;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @desc: OutputStream的包装类,在写入时记录写入的内容
+ */
+public abstract class OutputStreamProxy extends FilterOutputStream {
+ protected final ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream();
+
+
+ public OutputStreamProxy(@NonNull OutputStream out) {
+ super(out);
+ }
+
+ protected abstract void onStreamComplete() throws IOException;
+
+ @Override
+ public void flush() throws IOException {
+ super.flush();
+ onStreamComplete();
+ }
+
+ @Override
+ public void write(@NonNull byte[] b, int off, int len) throws IOException {
+ super.write(b, off, len);
+ mOutputStream.write(b, off, len);
+ }
+
+
+ @Override
+ public void close() throws IOException {
+ super.close();
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMainPagerFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMainPagerFragment.java
index eb3c2aef8..b5483a9cd 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMainPagerFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMainPagerFragment.java
@@ -22,7 +22,7 @@ public class NetWorkMainPagerFragment extends BaseFragment implements View.OnCli
@Override
protected int onRequestLayout() {
- return R.layout.fragment_net_main_pager;
+ return R.layout.dk_fragment_net_main_pager;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMonitorFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMonitorFragment.java
index 07be4b835..0a0a0cea5 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMonitorFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkMonitorFragment.java
@@ -25,7 +25,7 @@ public class NetWorkMonitorFragment extends BaseFragment implements OnFloatPageC
@Override
protected int onRequestLayout() {
- return R.layout.fragment_net_monitor;
+ return R.layout.dk_fragment_net_monitor;
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkSummaryView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkSummaryView.java
index 020f84ada..452cf8cc9 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkSummaryView.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetWorkSummaryView.java
@@ -21,13 +21,13 @@ public class NetWorkSummaryView extends LinearLayout {
public NetWorkSummaryView(Context context) {
super(context);
- inflate(context, R.layout.fragment_network_summary_page, this);
+ inflate(context, R.layout.dk_fragment_network_summary_page, this);
initView();
}
public NetWorkSummaryView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- inflate(context, R.layout.fragment_network_summary_page, this);
+ inflate(context, R.layout.dk_fragment_network_summary_page, this);
initView();
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailFragment.java
index fc02a3f46..993e52b4e 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailFragment.java
@@ -31,7 +31,7 @@ public class NetworkDetailFragment extends BaseFragment implements View.OnClickL
@Override
protected int onRequestLayout() {
- return R.layout.fragment_network_monitor_detail;
+ return R.layout.dk_fragment_network_monitor_detail;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailView.java
index ad90be548..9718473ba 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailView.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkDetailView.java
@@ -1,11 +1,15 @@
package com.didichuxing.doraemonkit.kit.network.ui;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.Context;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.Toast;
import com.didichuxing.doraemonkit.R;
import com.didichuxing.doraemonkit.kit.network.bean.NetworkRecord;
@@ -16,11 +20,13 @@
import java.text.SimpleDateFormat;
import java.util.Date;
+import static android.content.Context.CLIPBOARD_SERVICE;
+
/**
* @desc: 显示request和response的view
*/
public class NetworkDetailView extends LinearLayout {
- private SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MMdd-HH:mm:ss:SSS");
+ private SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss:SSS");
private TextView url;
private TextView method;
@@ -33,9 +39,13 @@ public class NetworkDetailView extends LinearLayout {
private TextView diverHeader;
private TextView diverBody;
- public NetworkDetailView(Context context) {
+ private ClipboardManager mClipboard;
+
+ public NetworkDetailView(final Context context) {
super(context);
- inflate(context, R.layout.view_network_request, this);
+ inflate(context, R.layout.dk_view_network_request, this);
+ mClipboard = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE);
+
url = findViewById(R.id.tv_url);
method = findViewById(R.id.tv_method);
size = findViewById(R.id.tv_data_size);
@@ -45,7 +55,15 @@ public NetworkDetailView(Context context) {
diverTime = findViewById(R.id.diver_time);
diverHeader = findViewById(R.id.diver_header);
diverBody = findViewById(R.id.diver_body);
-
+ body.setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ ClipData clipData = ClipData.newPlainText("Label", body.getText());
+ mClipboard.setPrimaryClip(clipData);
+ Toast.makeText(getContext(), "copy success", Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ });
}
public NetworkDetailView(Context context, @Nullable AttributeSet attrs) {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListAdapter.java
index 4910cecd8..80d94bd3c 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListAdapter.java
@@ -41,7 +41,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType)
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_network_list, parent, false);
+ return inflater.inflate(R.layout.dk_item_network_list, parent, false);
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListView.java
index 24a20d5e3..99f6e5f21 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListView.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/ui/NetworkListView.java
@@ -34,14 +34,14 @@ public class NetworkListView extends LinearLayout implements OnNetworkInfoUpdate
public NetworkListView(Context context) {
super(context);
- inflate(context, R.layout.fragment_network_monitor_list, this);
+ inflate(context, R.layout.dk_fragment_network_monitor_list, this);
initView();
initData();
}
public NetworkListView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- inflate(context, R.layout.fragment_network_monitor_list, this);
+ inflate(context, R.layout.dk_fragment_network_monitor_list, this);
initView();
initData();
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/AbsParameterFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/AbsParameterFragment.java
new file mode 100644
index 000000000..ea0071bf6
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/AbsParameterFragment.java
@@ -0,0 +1,164 @@
+package com.didichuxing.doraemonkit.kit.parameter;
+
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.CheckBox;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.ui.base.BaseFragment;
+import com.didichuxing.doraemonkit.ui.realtime.OnFloatPageChangeListener;
+import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartIconPage;
+import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartPage;
+import com.didichuxing.doraemonkit.ui.setting.SettingItem;
+import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
+import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public abstract class AbsParameterFragment extends BaseFragment implements OnFloatPageChangeListener {
+
+
+ private SettingItemAdapter mSettingItemAdapter;
+ private RecyclerView mSettingList;
+ private static final String[] PERMISSIONS_STORAGE = {
+ "android.permission.READ_EXTERNAL_STORAGE",
+ "android.permission.WRITE_EXTERNAL_STORAGE"};
+ private static final int REQUEST_EXTERNAL_STORAGE = 2;
+
+
+ @Override
+ protected int onRequestLayout() {
+ return R.layout.dk_fragment_parameter;
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ initView();
+ }
+
+ @StringRes
+ protected abstract int getTitle();
+
+ protected abstract Collection getSettingItems(List list);
+
+ protected abstract SettingItemAdapter.OnSettingItemSwitchListener getItemSwitchListener();
+
+ protected abstract SettingItemAdapter.OnSettingItemClickListener getItemClickListener();
+
+ protected void openChartPage(@StringRes int title, int type) {
+ RealTimeChartPage.openChartPage(getString(title), type, RealTimeChartPage.DEFAULT_REFRESH_INTERVAL, this);
+ }
+
+ protected void closeChartPage() {
+ RealTimeChartPage.closeChartPage();
+ }
+
+ private void initView() {
+ HomeTitleBar titleBar = findViewById(R.id.title_bar);
+ titleBar.setTitle(getTitle());
+ titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() {
+ @Override
+ public void onRightClick() {
+ getActivity().finish();
+ }
+ });
+
+ mSettingList = findViewById(R.id.setting_list);
+ mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
+ mSettingItemAdapter = new SettingItemAdapter(getContext());
+ mSettingItemAdapter.append(getSettingItems(new ArrayList()));
+
+ mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
+ @Override
+ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
+ if (on && !ownPermissionCheck()) {
+ if (view instanceof CheckBox) {
+ ((CheckBox) view).setChecked(false);
+ }
+ requestPermissions(PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
+ return;
+ }
+ SettingItemAdapter.OnSettingItemSwitchListener itemSwitchListener = getItemSwitchListener();
+ if (itemSwitchListener != null) {
+ itemSwitchListener.onSettingItemSwitch(view, data, on);
+ }
+ }
+ });
+ mSettingItemAdapter.setOnSettingItemClickListener(new SettingItemAdapter.OnSettingItemClickListener() {
+ @Override
+ public void onSettingItemClick(View view, SettingItem data) {
+ if (!ownPermissionCheck()) {
+ requestPermissions(PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
+ return;
+ }
+ SettingItemAdapter.OnSettingItemClickListener itemClickListener = getItemClickListener();
+ if (itemClickListener != null) {
+ itemClickListener.onSettingItemClick(view, data);
+ }
+
+ }
+ });
+ mSettingList.setAdapter(mSettingItemAdapter);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == REQUEST_EXTERNAL_STORAGE) {
+ for (int grantResult : grantResults) {
+ if (grantResult == -1) {
+ showToast(R.string.dk_error_tips_permissions_less);
+ }
+ }
+ }
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+
+ private boolean ownPermissionCheck() {
+
+ int permission = ActivityCompat.checkSelfPermission(getActivity(), "android.permission.WRITE_EXTERNAL_STORAGE");
+ if (permission != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void onFloatPageClose(String tag) {
+ if (!TextUtils.equals(RealTimeChartIconPage.TAG, tag)) {
+ return;
+ }
+ if (mSettingList == null || mSettingList.isComputingLayout()) {
+ return;
+ }
+ if (mSettingItemAdapter == null) {
+ return;
+ }
+ if (!mSettingItemAdapter.getData().get(0).isChecked) {
+ return;
+ }
+ mSettingItemAdapter.getData().get(0).isChecked = false;
+ mSettingItemAdapter.notifyItemChanged(0);
+ }
+
+ @Override
+ public void onFloatPageOpen(String tag) {
+
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ RealTimeChartPage.removeCloseListener();
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/cpu/Cpu.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/cpu/Cpu.java
similarity index 90%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/cpu/Cpu.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/cpu/Cpu.java
index 42ba76f85..f90fa2e5a 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/cpu/Cpu.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/cpu/Cpu.java
@@ -1,4 +1,4 @@
-package com.didichuxing.doraemonkit.kit.cpu;
+package com.didichuxing.doraemonkit.kit.parameter.cpu;
import android.content.Context;
import android.content.Intent;
@@ -18,7 +18,7 @@ public int getCategory() {
@Override
public int getName() {
- return R.string.dk_frameinfo_cpu;
+ return R.string.dk_fragment_parameter;
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/cpu/CpuMainPageFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/cpu/CpuMainPageFragment.java
new file mode 100644
index 000000000..0fe07fc4e
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/cpu/CpuMainPageFragment.java
@@ -0,0 +1,83 @@
+package com.didichuxing.doraemonkit.kit.parameter.cpu;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.PerformanceInfoConfig;
+import com.didichuxing.doraemonkit.constant.BundleKey;
+import com.didichuxing.doraemonkit.kit.parameter.AbsParameterFragment;
+import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager;
+import com.didichuxing.doraemonkit.kit.common.PerformanceFragment;
+import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory;
+import com.didichuxing.doraemonkit.ui.setting.SettingItem;
+import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
+
+import java.util.Collection;
+import java.util.List;
+
+public class CpuMainPageFragment extends AbsParameterFragment {
+ private static final String TAG = "CpuMainPageFragment";
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ PerformanceDataManager.getInstance().init(getContext().getApplicationContext());
+ }
+
+ @Override
+ protected int getTitle() {
+ return R.string.dk_fragment_parameter;
+ }
+
+ @Override
+ protected Collection getSettingItems(List list) {
+
+ list.add(new SettingItem(R.string.dk_cpu_detection_switch, PerformanceInfoConfig.isCPUOpen(getContext())));
+ list.add(new SettingItem(R.string.dk_item_cache_log, R.drawable.dk_more_icon));
+ return list;
+ }
+
+ @Override
+ protected SettingItemAdapter.OnSettingItemSwitchListener getItemSwitchListener() {
+ return new SettingItemAdapter.OnSettingItemSwitchListener() {
+ @Override
+ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
+ if (on) {
+ startMonitor();
+ } else {
+ stopMonitor();
+ }
+ PerformanceInfoConfig.setCPUOpen(getContext(), on);
+ }
+ };
+ }
+
+ @Override
+ protected SettingItemAdapter.OnSettingItemClickListener getItemClickListener() {
+ return new SettingItemAdapter.OnSettingItemClickListener() {
+ @Override
+ public void onSettingItemClick(View view, SettingItem data) {
+ if (data.desc == R.string.dk_item_cache_log) {
+
+ Bundle bundle = new Bundle();
+ bundle.putInt(BundleKey.PERFORMANCE_TYPE, PerformanceFragment.CPU);
+ showContent(PerformanceFragment.class, bundle);
+ }
+ }
+ };
+ }
+
+ private void startMonitor() {
+ PerformanceDataManager.getInstance().startMonitorCPUInfo();
+ openChartPage(R.string.dk_fragment_parameter, DataSourceFactory.TYPE_CPU);
+ }
+
+ private void stopMonitor() {
+ PerformanceDataManager.getInstance().stopMonitorCPUInfo();
+ closeChartPage();
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/frameInfo/FrameInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfo.java
similarity index 94%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/frameInfo/FrameInfo.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfo.java
index 3b038c866..b1058153e 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/frameInfo/FrameInfo.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfo.java
@@ -1,4 +1,4 @@
-package com.didichuxing.doraemonkit.kit.frameInfo;
+package com.didichuxing.doraemonkit.kit.parameter.frameInfo;
import android.content.Context;
import android.content.Intent;
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java
new file mode 100644
index 000000000..e4bdf5a64
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java
@@ -0,0 +1,78 @@
+package com.didichuxing.doraemonkit.kit.parameter.frameInfo;
+
+import android.os.Bundle;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.PerformanceInfoConfig;
+import com.didichuxing.doraemonkit.constant.BundleKey;
+import com.didichuxing.doraemonkit.kit.parameter.AbsParameterFragment;
+import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager;
+import com.didichuxing.doraemonkit.kit.common.PerformanceFragment;
+import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory;
+import com.didichuxing.doraemonkit.ui.setting.SettingItem;
+import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Created by wanglikun on 2018/9/13.
+ */
+
+public class FrameInfoFragment extends AbsParameterFragment {
+
+ @Override
+ protected int getTitle() {
+ return R.string.dk_kit_frame_info_desc;
+ }
+
+ @Override
+ protected Collection getSettingItems(List list) {
+ list.add(new SettingItem(R.string.dk_frameinfo_detection_switch, PerformanceInfoConfig.isFPSOpen(getContext())));
+ list.add(new SettingItem(R.string.dk_item_cache_log, R.drawable.dk_more_icon));
+ return list;
+ }
+
+ @Override
+ protected SettingItemAdapter.OnSettingItemSwitchListener getItemSwitchListener() {
+ return new SettingItemAdapter.OnSettingItemSwitchListener() {
+ @Override
+ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
+ if (on) {
+ startMonitor();
+ } else {
+ stopMonitor();
+ }
+ PerformanceInfoConfig.setFPSOpen(getContext(), on);
+ }
+ };
+ }
+
+ @Override
+ protected SettingItemAdapter.OnSettingItemClickListener getItemClickListener() {
+ return new SettingItemAdapter.OnSettingItemClickListener() {
+ @Override
+ public void onSettingItemClick(View view, SettingItem data) {
+ if (data.desc == R.string.dk_item_cache_log) {
+
+ Bundle bundle = new Bundle();
+ bundle.putInt(BundleKey.PERFORMANCE_TYPE, PerformanceFragment.FPS);
+ showContent(PerformanceFragment.class, bundle);
+ }
+
+ }
+ };
+ }
+
+ private void startMonitor() {
+ PerformanceDataManager.getInstance().startMonitorFrameInfo();
+ openChartPage(R.string.dk_frameinfo_fps, DataSourceFactory.TYPE_FRAME);
+ }
+
+ private void stopMonitor() {
+ PerformanceDataManager.getInstance().stopMonitorFrameInfo();
+ closeChartPage();
+ }
+
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/ram/Ram.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/ram/Ram.java
similarity index 94%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/ram/Ram.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/ram/Ram.java
index 63c4d0e72..82092fd72 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/ram/Ram.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/ram/Ram.java
@@ -1,4 +1,4 @@
-package com.didichuxing.doraemonkit.kit.ram;
+package com.didichuxing.doraemonkit.kit.parameter.ram;
import android.content.Context;
import android.content.Intent;
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/ram/RamMainPageFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/ram/RamMainPageFragment.java
new file mode 100644
index 000000000..7d7581bba
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/ram/RamMainPageFragment.java
@@ -0,0 +1,84 @@
+package com.didichuxing.doraemonkit.kit.parameter.ram;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.PerformanceInfoConfig;
+import com.didichuxing.doraemonkit.constant.BundleKey;
+import com.didichuxing.doraemonkit.kit.parameter.AbsParameterFragment;
+import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager;
+import com.didichuxing.doraemonkit.kit.common.PerformanceFragment;
+import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory;
+import com.didichuxing.doraemonkit.ui.setting.SettingItem;
+import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
+
+import java.util.Collection;
+import java.util.List;
+
+public class RamMainPageFragment extends AbsParameterFragment {
+ private static final String TAG = "RamMainPageFragment";
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ PerformanceDataManager.getInstance().init(getContext().getApplicationContext());
+ }
+
+ @Override
+ protected int getTitle() {
+ return R.string.dk_ram_detection_title;
+ }
+
+ @Override
+ protected Collection getSettingItems(List list) {
+ list.add(new SettingItem(R.string.dk_ram_detection_switch, PerformanceInfoConfig.isMemoryOpen(getContext())));
+ list.add(new SettingItem(R.string.dk_item_cache_log, R.drawable.dk_more_icon));
+ return list;
+ }
+
+ @Override
+ protected SettingItemAdapter.OnSettingItemSwitchListener getItemSwitchListener() {
+ return new SettingItemAdapter.OnSettingItemSwitchListener() {
+ @Override
+ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
+ if (on) {
+ startMonitor();
+ } else {
+ stopMonitor();
+ }
+ PerformanceInfoConfig.setMemoryOpen(getContext(), on);
+ }
+
+ };
+ }
+
+ @Override
+ protected SettingItemAdapter.OnSettingItemClickListener getItemClickListener() {
+ return new SettingItemAdapter.OnSettingItemClickListener() {
+ @Override
+ public void onSettingItemClick(View view, SettingItem data) {
+ if (data.desc == R.string.dk_item_cache_log) {
+ Bundle bundle = new Bundle();
+ bundle.putInt(BundleKey.PERFORMANCE_TYPE, PerformanceFragment.RAM);
+ showContent(PerformanceFragment.class, bundle);
+
+ }
+ }
+ };
+ }
+
+ protected void startMonitor() {
+ PerformanceDataManager.getInstance().startMonitorMemoryInfo();
+ openChartPage(R.string.dk_ram_detection_title, DataSourceFactory.TYPE_MEMORY);
+ }
+
+ protected void stopMonitor() {
+ PerformanceDataManager.getInstance().stopMonitorMemoryInfo();
+ closeChartPage();
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/ram/RamMainPageFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/ram/RamMainPageFragment.java
deleted file mode 100644
index 6d8baaf1f..000000000
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/ram/RamMainPageFragment.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.didichuxing.doraemonkit.kit.ram;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
-import android.view.View;
-
-import com.didichuxing.doraemonkit.R;
-import com.didichuxing.doraemonkit.config.PerformanceInfoConfig;
-import com.didichuxing.doraemonkit.constant.BundleKey;
-import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager;
-import com.didichuxing.doraemonkit.kit.common.PerformanceFragment;
-import com.didichuxing.doraemonkit.ui.base.BaseFragment;
-import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory;
-import com.didichuxing.doraemonkit.ui.realtime.OnFloatPageChangeListener;
-import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartIconPage;
-import com.didichuxing.doraemonkit.ui.realtime.RealTimeChartPage;
-import com.didichuxing.doraemonkit.ui.setting.SettingItem;
-import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
-import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
-
-public class RamMainPageFragment extends BaseFragment implements OnFloatPageChangeListener {
- private static final String TAG = "RamMainPageFragment";
- private SettingItemAdapter mSettingItemAdapter;
- private RecyclerView mSettingList;
-
- @Override
- protected int onRequestLayout() {
- return R.layout.fragment_cpu_main_page;
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- PerformanceDataManager.getInstance().init(getContext().getApplicationContext());
- initView();
- }
-
- private void initView() {
- HomeTitleBar titleBar = findViewById(R.id.title_bar);
- titleBar.setTitle(R.string.dk_ram_detection_title);
- titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() {
- @Override
- public void onRightClick() {
- getActivity().finish();
- }
- });
-
- mSettingList = findViewById(R.id.setting_list);
- mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
- mSettingItemAdapter = new SettingItemAdapter(getContext());
- mSettingItemAdapter.append(new SettingItem(R.string.dk_ram_detection_switch, PerformanceInfoConfig.isMemoryOpen(getContext())));
- mSettingItemAdapter.append(new SettingItem(R.string.dk_item_cache_log, R.drawable.dk_more_icon));
-
- mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
- @Override
- public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
- if (data.desc == R.string.dk_ram_detection_switch) {
- if (on) {
- startMonitor();
- } else {
- stopMonitor();
- }
- PerformanceInfoConfig.setMemoryOpen(getContext(), on);
- }
- }
- });
- mSettingItemAdapter.setOnSettingItemClickListener(new SettingItemAdapter.OnSettingItemClickListener() {
- @Override
- public void onSettingItemClick(View view, SettingItem data) {
- if (data.desc == R.string.dk_item_cache_log) {
- Bundle bundle = new Bundle();
- bundle.putInt(BundleKey.PERFORMANCE_TYPE, PerformanceFragment.RAM);
- showContent(PerformanceFragment.class, bundle);
- }
- }
- });
- mSettingList.setAdapter(mSettingItemAdapter);
-// if (PerformanceInfoConfig.isMemoryOpen(getContext())) {
-// startMonitor();
-// }
- }
-
- private void startMonitor() {
- PerformanceDataManager.getInstance().startMonitorMemoryInfo();
- String title = getString(R.string.dk_ram_detection_title);
- int type = DataSourceFactory.TYPE_MEMORY;
- RealTimeChartPage.openChartPage(title, type, RealTimeChartPage.DEFAULT_REFRESH_INTERVAL, this);
- }
-
- private void stopMonitor() {
- PerformanceDataManager.getInstance().stopMonitorMemoryInfo();
- RealTimeChartPage.closeChartPage();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- RealTimeChartPage.removeCloseListener();
- }
-
- @Override
- public void onFloatPageClose(String tag) {
- if (!TextUtils.equals(RealTimeChartIconPage.TAG, tag)) {
- return;
- }
- if (mSettingList == null || mSettingList.isComputingLayout()) {
- return;
- }
- if (mSettingItemAdapter == null) {
- return;
- }
- if (!mSettingItemAdapter.getData().get(0).isChecked) {
- return;
- }
- mSettingItemAdapter.getData().get(0).isChecked = false;
- mSettingItemAdapter.notifyItemChanged(0);
- }
-
- @Override
- public void onFloatPageOpen(String tag) {
-
- }
-}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoFragment.java
index c638dd78b..c7dc93540 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoFragment.java
@@ -18,6 +18,7 @@
import com.didichuxing.doraemonkit.ui.widget.recyclerview.DividerItemDecoration;
import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
import com.didichuxing.doraemonkit.util.DeviceUtils;
+import com.didichuxing.doraemonkit.util.ExecutorUtil;
import com.didichuxing.doraemonkit.util.PermissionUtil;
import com.didichuxing.doraemonkit.util.UIUtils;
@@ -36,7 +37,7 @@ public class SysInfoFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_sys_info;
+ return R.layout.dk_fragment_sys_info;
}
@Override
@@ -111,7 +112,7 @@ private void addDeviceData(List sysInfoItems) {
* 不可靠的检测权限方式
*/
private void addPermissionDataUnreliable() {
- new Thread("check-permission") {
+ ExecutorUtil.execute(new Runnable() {
@Override
public void run() {
final List list = new ArrayList<>();
@@ -132,7 +133,7 @@ public void run() {
}
});
}
- }.start();
+ });
}
@TargetApi(Build.VERSION_CODES.M)
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoItemAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoItemAdapter.java
index 65e388c89..600109743 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoItemAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/sysinfo/SysInfoItemAdapter.java
@@ -46,9 +46,9 @@ public int getItemViewType(int position) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
if (viewType == TYPE_TITLE) {
- return inflater.inflate(R.layout.item_sys_title, parent, false);
+ return inflater.inflate(R.layout.dk_item_sys_title, parent, false);
} else {
- return inflater.inflate(R.layout.item_sys_info, parent, false);
+ return inflater.inflate(R.layout.dk_item_sys_info, parent, false);
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/temporaryclose/TemporaryClose.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/temporaryclose/TemporaryClose.java
index 75e5ae569..338ca7c56 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/temporaryclose/TemporaryClose.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/temporaryclose/TemporaryClose.java
@@ -2,10 +2,10 @@
import android.content.Context;
+import com.didichuxing.doraemonkit.DoraemonKit;
import com.didichuxing.doraemonkit.R;
import com.didichuxing.doraemonkit.kit.Category;
import com.didichuxing.doraemonkit.kit.IKit;
-import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
/**
* Created by wanglikun on 2018/10/26.
@@ -29,7 +29,7 @@ public int getIcon() {
@Override
public void onClick(Context context) {
- FloatPageManager.getInstance().removeAll();
+ DoraemonKit.hide();
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/PrinterParser.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/PrinterParser.java
new file mode 100644
index 000000000..7cdaa9d71
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/PrinterParser.java
@@ -0,0 +1,112 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.text.TextUtils;
+import android.util.Printer;
+
+import com.didichuxing.doraemonkit.util.LogHelper;
+
+/**
+ * @author: linjizong
+ * @date: 2019/2/19
+ * @desc:
+ */
+public class PrinterParser implements Printer {
+ private static final String DISPATCHING_TAG = ">>>>> Dispatching";
+ private static final String FINISHED_TAG = "<<<<< Finished";
+ private static final String HANDLER_NAME = "android.app.ActivityThread$H";
+
+ public static final int LAUNCH_ACTIVITY = 100;
+ public static final int PAUSE_ACTIVITY = 101;
+ public static final int PAUSE_ACTIVITY_FINISHING = 102;
+ public static final int STOP_ACTIVITY_SHOW = 103;
+ public static final int STOP_ACTIVITY_HIDE = 104;
+ public static final int SHOW_WINDOW = 105;
+ public static final int HIDE_WINDOW = 106;
+ public static final int RESUME_ACTIVITY = 107;
+ public static final int SEND_RESULT = 108;
+ public static final int DESTROY_ACTIVITY = 109;
+ public static final int BIND_APPLICATION = 110;
+ public static final int EXIT_APPLICATION = 111;
+ public static final int NEW_INTENT = 112;
+ public static final int RECEIVER = 113;
+ public static final int CREATE_SERVICE = 114;
+ public static final int SERVICE_ARGS = 115;
+ public static final int STOP_SERVICE = 116;
+
+ public static final int CONFIGURATION_CHANGED = 118;
+ public static final int CLEAN_UP_CONTEXT = 119;
+ public static final int GC_WHEN_IDLE = 120;
+ public static final int BIND_SERVICE = 121;
+ public static final int UNBIND_SERVICE = 122;
+ public static final int DUMP_SERVICE = 123;
+ public static final int LOW_MEMORY = 124;
+ public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
+ public static final int RELAUNCH_ACTIVITY = 126;
+ public static final int PROFILER_CONTROL = 127;
+ public static final int CREATE_BACKUP_AGENT = 128;
+ public static final int DESTROY_BACKUP_AGENT = 129;
+ public static final int SUICIDE = 130;
+ public static final int REMOVE_PROVIDER = 131;
+ public static final int ENABLE_JIT = 132;
+ public static final int DISPATCH_PACKAGE_BROADCAST = 133;
+ public static final int SCHEDULE_CRASH = 134;
+ public static final int DUMP_HEAP = 135;
+ public static final int DUMP_ACTIVITY = 136;
+ public static final int SLEEPING = 137;
+ public static final int SET_CORE_SETTINGS = 138;
+ public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
+ public static final int TRIM_MEMORY = 140;
+ public static final int DUMP_PROVIDER = 141;
+ public static final int UNSTABLE_PROVIDER_DIED = 142;
+ public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
+ public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
+ public static final int INSTALL_PROVIDER = 145;
+ public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
+ public static final int CANCEL_VISIBLE_BEHIND = 147;
+ public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
+ public static final int ENTER_ANIMATION_COMPLETE = 149;
+ public static final int START_BINDER_TRACKING = 150;
+ public static final int STOP_BINDER_TRACKING_AND_DUMP = 151;
+ public static final int MULTI_WINDOW_MODE_CHANGED = 152;
+ public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
+ public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
+ public static final int ATTACH_AGENT = 155;
+ public static final int APPLICATION_INFO_CHANGED = 156;
+ public static final int ACTIVITY_MOVED_TO_DISPLAY = 157;
+
+ private int sCurrentMsg;
+
+ public void parse(String log) {
+ if (TextUtils.isEmpty(log)) {
+ return;
+ }
+ if (!log.contains(HANDLER_NAME)) {
+ return;
+ }
+ if (log.startsWith(DISPATCHING_TAG)) {
+ if (log.endsWith(String.valueOf(PAUSE_ACTIVITY))) {
+ LogHelper.d("PinterParser", "pause");
+ TimeCounterManager.get().onActivityStart();
+ sCurrentMsg = PAUSE_ACTIVITY;
+ } else if (log.endsWith(String.valueOf(LAUNCH_ACTIVITY))) {
+ LogHelper.d("PinterParser", "launch");
+ TimeCounterManager.get().onActivityLaunch();
+ sCurrentMsg = LAUNCH_ACTIVITY;
+ }
+ } else if (log.startsWith(FINISHED_TAG)) {
+ if (sCurrentMsg == PAUSE_ACTIVITY) {
+ LogHelper.d("PinterParser", "pause end");
+ TimeCounterManager.get().onActivityPaused();
+ } else if (sCurrentMsg == LAUNCH_ACTIVITY) {
+ LogHelper.d("PinterParser", "launch end");
+ TimeCounterManager.get().onActivityCreated();
+ }
+ sCurrentMsg = 0;
+ }
+ }
+
+ @Override
+ public void println(String x) {
+ parse(x);
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterFloatPage.java
new file mode 100644
index 000000000..9f5a562c1
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterFloatPage.java
@@ -0,0 +1,165 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo;
+import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
+import com.didichuxing.doraemonkit.util.UIUtils;
+
+/**
+ */
+
+public class TimeCounterFloatPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener {
+ private WindowManager mWindowManager;
+ private TextView tvTitle;
+ private TextView tvTotal;
+ private TextView tvPause;
+ private TextView tvLaunch;
+ private TextView tvRender;
+ private TextView tvOther;
+ private ImageView mClose;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
+
+ @Override
+ protected void onCreate(Context context) {
+ super.onCreate(context);
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ }
+
+ @Override
+ protected View onCreateView(Context context, ViewGroup view) {
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_time_counter, null);
+ }
+
+ @Override
+ protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
+ params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ params.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ params.x = UIUtils.dp2px(getContext(), 30);
+ params.y = UIUtils.dp2px(getContext(), 30);
+ }
+
+ @Override
+ protected void onViewCreated(View view) {
+ super.onViewCreated(view);
+ initView();
+ }
+
+ private void initView() {
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
+ tvTitle = findViewById(R.id.title);
+ tvTotal = findViewById(R.id.total_cost);
+ tvPause = findViewById(R.id.pause_cost);
+ tvLaunch = findViewById(R.id.launch_cost);
+ tvRender = findViewById(R.id.render_cost);
+ tvOther = findViewById(R.id.other_cost);
+
+ CounterInfo counterInfo = TimeCounterManager.get().getAppSetupInfo();
+ showInfo(counterInfo);
+
+ mClose = findViewById(R.id.close);
+ mClose.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ TimeCounterManager.get().stop();
+ }
+ });
+ }
+
+ public void showInfo(CounterInfo info) {
+ tvTitle.setText(info.title);
+ setTotalCost(info.totalCost);
+
+ if (info.type == CounterInfo.TYPE_ACTIVITY) {
+ tvPause.setVisibility(View.VISIBLE);
+ tvLaunch.setVisibility(View.VISIBLE);
+ tvRender.setVisibility(View.VISIBLE);
+ tvOther.setVisibility(View.VISIBLE);
+
+ tvPause.setText("Pause Cost: " + info.pauseCost + "ms");
+ tvLaunch.setText("Launch Cost: " + info.launchCost + "ms");
+ tvRender.setText("Render Cost: " + info.renderCost + "ms");
+ tvOther.setText("Other Cost: " + info.otherCost + "ms");
+ } else {
+ tvPause.setVisibility(View.GONE);
+ tvLaunch.setVisibility(View.GONE);
+ tvRender.setVisibility(View.GONE);
+ tvOther.setVisibility(View.GONE);
+ }
+ }
+
+ private void setTotalCost(long cost) {
+ tvTotal.setText("Total Cost: " + cost + "ms");
+ if (cost <= CounterInfo.ACTIVITY_COST_FAST) {
+ tvTotal.setTextColor(getContext().getResources().getColor(R.color.dk_color_48BB31));
+ } else if (cost <= CounterInfo.ACTIVITY_COST_SLOW) {
+ tvTotal.setTextColor(getContext().getResources().getColor(R.color.dk_color_FAD337));
+ } else {
+ tvTotal.setTextColor(getContext().getResources().getColor(R.color.dk_color_FF0006));
+ }
+ }
+
+ private void showDetail(CounterInfo info) {
+ if (info.type == CounterInfo.TYPE_APP) {
+ info.show = false;
+ }
+ if (info.show) {
+ tvPause.setVisibility(View.VISIBLE);
+ tvLaunch.setVisibility(View.VISIBLE);
+ tvRender.setVisibility(View.VISIBLE);
+ tvOther.setVisibility(View.VISIBLE);
+
+
+ } else {
+ tvPause.setVisibility(View.GONE);
+ tvLaunch.setVisibility(View.GONE);
+ tvRender.setVisibility(View.GONE);
+ tvOther.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
+ }
+
+ @Override
+ public void onEnterForeground() {
+ super.onEnterForeground();
+ getRootView().setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onEnterBackground() {
+ super.onEnterBackground();
+ getRootView().setVisibility(View.GONE);
+ TimeCounterManager.get().onEnterBackground();
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterFragment.java
new file mode 100644
index 000000000..2a4483769
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterFragment.java
@@ -0,0 +1,81 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.ui.base.BaseFragment;
+import com.didichuxing.doraemonkit.ui.setting.SettingItem;
+import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter;
+import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar;
+
+/**
+ * @desc: Activity跳转耗时检测首页
+ */
+
+public class TimeCounterFragment extends BaseFragment {
+
+ @Override
+ protected int onRequestLayout() {
+ return R.layout.dk_fragment_time_counter_index;
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ initView();
+ }
+
+
+ private void initView() {
+ HomeTitleBar title = findViewById(R.id.title_bar);
+ title.setListener(new HomeTitleBar.OnTitleBarClickListener() {
+ @Override
+ public void onRightClick() {
+ getActivity().finish();
+ }
+ });
+ RecyclerView mSettingList = findViewById(R.id.setting_list);
+ mSettingList.setLayoutManager(new LinearLayoutManager(getContext()));
+ SettingItemAdapter settingItemAdapter = new SettingItemAdapter(getContext());
+ mSettingList.setAdapter(settingItemAdapter);
+ settingItemAdapter.append(new SettingItem(R.string.dk_item_time_counter_switch, TimeCounterManager.get().isRunning()));
+ settingItemAdapter.append(new SettingItem(R.string.dk_item_time_goto_list));
+
+ settingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() {
+ @Override
+ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
+ if (data.desc == R.string.dk_item_time_counter_switch) {
+ if (on) {
+ TimeCounterManager.get().start();
+ } else {
+ TimeCounterManager.get().stop();
+ }
+ }
+ }
+ });
+ settingItemAdapter.setOnSettingItemClickListener(new SettingItemAdapter.OnSettingItemClickListener() {
+ @Override
+ public void onSettingItemClick(View view, SettingItem data) {
+ if (data.desc == R.string.dk_item_time_goto_list) {
+ showContent(TimeCounterListFragment.class);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterKit.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterKit.java
new file mode 100644
index 000000000..943fd711b
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterKit.java
@@ -0,0 +1,46 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.constant.BundleKey;
+import com.didichuxing.doraemonkit.constant.FragmentIndex;
+import com.didichuxing.doraemonkit.kit.Category;
+import com.didichuxing.doraemonkit.kit.IKit;
+import com.didichuxing.doraemonkit.ui.UniversalActivity;
+
+/**
+ * app启动、页面跳转的计时kit
+ */
+
+public class TimeCounterKit implements IKit {
+ @Override
+ public int getCategory() {
+ return Category.TOOLS;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_kit_time_counter;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.drawable.dk_time_counter;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Intent intent = new Intent(context, UniversalActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(BundleKey.FRAGMENT_INDEX, FragmentIndex.FRAGMENT_TIME_COUNTER);
+ context.startActivity(intent);
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java
new file mode 100644
index 000000000..cef56df11
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListAdapter.java
@@ -0,0 +1,115 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.content.Context;
+import android.text.format.DateUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo;
+import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsRecyclerAdapter;
+import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsViewBinder;
+
+import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
+
+public class TimeCounterListAdapter extends AbsRecyclerAdapter, CounterInfo> {
+
+
+ public TimeCounterListAdapter(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected AbsViewBinder createViewHolder(View view, int viewType) {
+ return new ItemViewHolder(view);
+ }
+
+ @Override
+ protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
+ return inflater.inflate(R.layout.dk_item_time_counter_list, parent, false);
+ }
+
+ private class ItemViewHolder extends AbsViewBinder {
+
+ private TextView tvTime;
+ private TextView tvTitle;
+ private TextView tvTotal;
+ private TextView tvPause;
+ private TextView tvLaunch;
+ private TextView tvRender;
+ private TextView tvOther;
+
+ public ItemViewHolder(View view) {
+ super(view);
+ }
+
+ @Override
+ protected void getViews() {
+ tvTime = getView(R.id.time);
+ tvTitle = getView(R.id.title);
+ tvTotal = getView(R.id.total_cost);
+ tvPause = getView(R.id.pause_cost);
+ tvLaunch = getView(R.id.launch_cost);
+ tvRender = getView(R.id.render_cost);
+ tvOther = getView(R.id.other_cost);
+ }
+
+ @Override
+ public void bind(CounterInfo counterInfo) {
+
+ }
+
+ @Override
+ public void bind(final CounterInfo info, int position) {
+ tvTitle.setText(info.title);
+ String time = DateUtils.formatDateTime(getContext(),
+ info.time, FORMAT_SHOW_TIME);
+ tvTime.setText(time);
+ setTotalCost(info.totalCost);
+ itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ info.show = !info.show;
+ showDetail(info);
+ }
+ });
+ showDetail(info);
+ }
+
+ private void setTotalCost(long cost) {
+ tvTotal.setText("Total Cost: " + cost + "ms");
+ if (cost <= CounterInfo.ACTIVITY_COST_FAST) {
+ tvTotal.setTextColor(getContext().getResources().getColor(R.color.dk_color_48BB31));
+ } else if (cost <= CounterInfo.ACTIVITY_COST_SLOW) {
+ tvTotal.setTextColor(getContext().getResources().getColor(R.color.dk_color_FAD337));
+ } else {
+ tvTotal.setTextColor(getContext().getResources().getColor(R.color.dk_color_FF0006));
+ }
+ }
+
+ private void showDetail(CounterInfo info) {
+ if (info.type == CounterInfo.TYPE_APP) {
+ info.show = false;
+ }
+ if (info.show) {
+ tvPause.setVisibility(View.VISIBLE);
+ tvLaunch.setVisibility(View.VISIBLE);
+ tvRender.setVisibility(View.VISIBLE);
+ tvOther.setVisibility(View.VISIBLE);
+
+ tvPause.setText("Pause Cost: " + info.pauseCost + "ms");
+ tvLaunch.setText("Launch Cost: " + info.launchCost + "ms");
+ tvRender.setText("Render Cost: " + info.renderCost + "ms");
+ tvOther.setText("Other Cost: " + info.otherCost + "ms");
+ } else {
+ tvPause.setVisibility(View.GONE);
+ tvLaunch.setVisibility(View.GONE);
+ tvRender.setVisibility(View.GONE);
+ tvOther.setVisibility(View.GONE);
+ }
+ }
+ }
+}
+
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListFragment.java
new file mode 100644
index 000000000..14e34241d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterListFragment.java
@@ -0,0 +1,84 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo;
+import com.didichuxing.doraemonkit.ui.base.BaseFragment;
+import com.didichuxing.doraemonkit.ui.widget.recyclerview.DividerItemDecoration;
+import com.didichuxing.doraemonkit.ui.widget.titlebar.TitleBar;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @desc: 跳转耗时历史记录列表
+ */
+
+public class TimeCounterListFragment extends BaseFragment {
+ private static final String TAG = "TimeCounterListFragment";
+
+ private RecyclerView mBlockList;
+ private TimeCounterListAdapter mAdapter;
+ private TitleBar mTitleBar;
+
+ @Override
+ protected int onRequestLayout() {
+ return R.layout.dk_fragment_time_counter_list;
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ initView();
+ load();
+ }
+
+
+ private void initView() {
+ mBlockList = findViewById(R.id.block_list);
+
+ LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
+ mBlockList.setLayoutManager(layoutManager);
+ mAdapter = new TimeCounterListAdapter(getContext());
+ mBlockList.setAdapter(mAdapter);
+ DividerItemDecoration decoration = new DividerItemDecoration(DividerItemDecoration.VERTICAL);
+ decoration.setDrawable(getResources().getDrawable(R.drawable.dk_divider));
+ mBlockList.addItemDecoration(decoration);
+ mTitleBar = findViewById(R.id.title_bar);
+ mTitleBar.setOnTitleBarClickListener(new TitleBar.OnTitleBarClickListener() {
+ @Override
+ public void onLeftClick() {
+ getActivity().onBackPressed();
+ }
+
+ @Override
+ public void onRightClick() {
+
+ }
+ });
+ }
+
+
+ private void load() {
+ List infos = new ArrayList<>(TimeCounterManager.get().getHistory());
+ infos.add(0, TimeCounterManager.get().getAppSetupInfo());
+ Collections.sort(infos, new Comparator() {
+ @Override
+ public int compare(CounterInfo lhs, CounterInfo rhs) {
+ return Long.valueOf(rhs.time)
+ .compareTo(lhs.time);
+ }
+ });
+ mAdapter.setData(infos);
+ }
+
+
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java
new file mode 100644
index 000000000..a9b3c204d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java
@@ -0,0 +1,99 @@
+package com.didichuxing.doraemonkit.kit.timecounter;
+
+import android.os.Looper;
+
+import com.didichuxing.doraemonkit.constant.PageTag;
+import com.didichuxing.doraemonkit.kit.blockmonitor.core.BlockMonitorManager;
+import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo;
+import com.didichuxing.doraemonkit.kit.timecounter.counter.ActivityCounter;
+import com.didichuxing.doraemonkit.kit.timecounter.counter.AppCounter;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.PageIntent;
+
+import java.util.List;
+
+/**
+ * @desc: App启动、Activity跳转的耗时统计类
+ */
+public class TimeCounterManager {
+ private boolean mIsRunning;
+
+ private static class Holder {
+ private static TimeCounterManager INSTANCE = new TimeCounterManager();
+ }
+
+ private PrinterParser mParser = new PrinterParser();
+
+ public static TimeCounterManager get() {
+ return TimeCounterManager.Holder.INSTANCE;
+ }
+
+ private AppCounter mAppCounter = new AppCounter();
+ private ActivityCounter mActivityCounter = new ActivityCounter();
+
+ public void onAppCreateStart() {
+ mAppCounter.start();
+ }
+
+ public void onAppCreateEnd() {
+ mAppCounter.end();
+ }
+
+ public long getAppInitTime() {
+ return mAppCounter.getTime();
+ }
+
+ public void onActivityStart() {
+ mActivityCounter.start();
+ }
+
+ public void onActivityPaused() {
+ mActivityCounter.paused();
+ }
+
+ public void onActivityLaunch() {
+ mActivityCounter.launch();
+ }
+
+ public void onActivityCreated() {
+ mActivityCounter.launchEnd();
+ }
+
+ public void onEnterBackground() {
+ mActivityCounter.enterBackground();
+ }
+
+ public void start() {
+ if (mIsRunning) {
+ return;
+ }
+ mIsRunning = true;
+ // 卡顿检测和跳转耗时统计都使用了Printer的方式,无法同时工作
+ BlockMonitorManager.getInstance().stop();
+ Looper.getMainLooper().setMessageLogging(mParser);
+ PageIntent pageIntent = new PageIntent(TimeCounterFloatPage.class);
+ pageIntent.tag = PageTag.PAGE_TIME_COUNTER;
+ pageIntent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(pageIntent);
+ }
+
+ public boolean isRunning() {
+ return mIsRunning;
+ }
+
+ public void stop() {
+ if (!mIsRunning) {
+ return;
+ }
+ Looper.getMainLooper().setMessageLogging(null);
+ mIsRunning = false;
+ FloatPageManager.getInstance().remove(PageTag.PAGE_TIME_COUNTER);
+ }
+
+ public List getHistory() {
+ return mActivityCounter.getHistory();
+ }
+ public CounterInfo getAppSetupInfo(){
+ return mAppCounter.getAppSetupInfo();
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/bean/CounterInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/bean/CounterInfo.java
new file mode 100644
index 000000000..23502c55f
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/bean/CounterInfo.java
@@ -0,0 +1,23 @@
+package com.didichuxing.doraemonkit.kit.timecounter.bean;
+
+/**
+ * @desc: 统计耗时的Bean
+ */
+public class CounterInfo {
+ public static final int ACTIVITY_COST_FAST = 500;
+ public static final int ACTIVITY_COST_SLOW = 1000;
+
+ public static final int TYPE_APP = 0;
+ public static final int TYPE_ACTIVITY = 1;
+
+ public long time;
+ public int type;
+ public String title;
+ public long totalCost;
+ public long pauseCost;
+ public long launchCost;
+ public long renderCost;
+ public long otherCost;
+
+ public boolean show;
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java
new file mode 100644
index 000000000..80c0da77d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java
@@ -0,0 +1,131 @@
+package com.didichuxing.doraemonkit.kit.timecounter.counter;
+
+import android.app.Activity;
+
+import com.didichuxing.doraemonkit.DoraemonKit;
+import com.didichuxing.doraemonkit.constant.PageTag;
+import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterFloatPage;
+import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.util.LogHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 统计一个打开Activity操作的耗时分三个阶段,以A打开B为例,第一个阶段是A的pause操作,主要是onPause方法的耗时,第二个阶段是B的Launch操作,主要是
+ * onCreate和onResume方法的耗时,第三个阶段是B的Window的渲染操作,调用DecorView的post方法进行统计
+ * 这里忽略了和AMS、WMS进行通讯的耗时,主要是因为这部分耗时无法通过非侵入式方式统计,而且用户也无法对这部分耗时做优化(除非重写Activity调用AMS的逻辑),
+ * 总耗时=pause+launch+render+other
+ */
+public class ActivityCounter {
+
+ private static final String TAG = "ActivityCounter";
+ private long mStartTime;
+ private long mPauseCostTime;
+ private long mLaunchStartTime;
+ private long mLaunchCostTime;
+ private long mRenderStartTime;
+ private long mRenderCostTime;
+ private long mTotalCostTime;
+ private long mOtherCostTime;
+
+ private String mPreviousActivity;
+ private String mCurrentActivity;
+ private List mCounterInfos = new ArrayList<>();
+
+ public void start() {
+ mStartTime = System.currentTimeMillis();
+ mPauseCostTime = 0;
+ mRenderCostTime = 0;
+ mOtherCostTime = 0;
+ mLaunchCostTime = 0;
+ mLaunchStartTime = 0;
+ mTotalCostTime = 0;
+ mPreviousActivity = null;
+ Activity activity = DoraemonKit.getCurrentResumedActivity();
+ if (activity != null) {
+ mPreviousActivity = activity.getClass().getSimpleName();
+ }
+ }
+
+ public void paused() {
+ mPauseCostTime = System.currentTimeMillis() - mStartTime;
+ LogHelper.d(TAG, "pause cost:" + mPauseCostTime);
+ }
+
+ public void launch() {
+ // 可能不走pause,直接打开新页面,比如从后台点击通知栏
+ if (mStartTime == 0) {
+ mStartTime = System.currentTimeMillis();
+ mPauseCostTime = 0;
+ mRenderCostTime = 0;
+ mOtherCostTime = 0;
+ mLaunchCostTime = 0;
+ mLaunchStartTime = 0;
+ mTotalCostTime = 0;
+ }
+ mLaunchStartTime = System.currentTimeMillis();
+ mLaunchCostTime = 0;
+ }
+
+ public void launchEnd() {
+ mLaunchCostTime = System.currentTimeMillis() - mLaunchStartTime;
+ LogHelper.d(TAG, "create cost:" + mLaunchCostTime);
+ render();
+ }
+
+ public void render() {
+ mRenderStartTime = System.currentTimeMillis();
+ Activity activity = DoraemonKit.getCurrentResumedActivity();
+ if (activity != null && activity.getWindow() != null) {
+ mCurrentActivity = activity.getClass().getSimpleName();
+ activity.getWindow().getDecorView().post(new Runnable() {
+ @Override
+ public void run() {
+ renderEnd();
+ }
+ });
+ } else {
+ renderEnd();
+ }
+ }
+
+ /**
+ * 用户退到后台,点击通知栏打开新页面,这时候需要清空下上次pause记录的时间
+ */
+ public void enterBackground() {
+ mStartTime = 0;
+ }
+
+ public void renderEnd() {
+ mRenderCostTime = System.currentTimeMillis() - mRenderStartTime;
+ LogHelper.d(TAG, "render cost:" + mRenderCostTime);
+ mTotalCostTime = System.currentTimeMillis() - mStartTime;
+ LogHelper.d(TAG, "total cost:" + mTotalCostTime);
+ mOtherCostTime = mTotalCostTime - mRenderCostTime - mPauseCostTime - mLaunchCostTime;
+ print();
+ }
+
+ public void print() {
+ TimeCounterFloatPage page = (TimeCounterFloatPage) FloatPageManager.getInstance().getFloatPage(PageTag.PAGE_TIME_COUNTER);
+
+ CounterInfo counterInfo = new CounterInfo();
+ counterInfo.time = System.currentTimeMillis();
+ counterInfo.type = CounterInfo.TYPE_ACTIVITY;
+ counterInfo.title = mPreviousActivity + " -> " + mCurrentActivity;
+ counterInfo.launchCost = mLaunchCostTime;
+ counterInfo.pauseCost = mPauseCostTime;
+ counterInfo.renderCost = mRenderCostTime;
+ counterInfo.totalCost = mTotalCostTime;
+ counterInfo.otherCost = mOtherCostTime;
+ mCounterInfos.add(counterInfo);
+ if (page != null) {
+ page.showInfo(counterInfo);
+ }
+ }
+
+ public List getHistory() {
+ return mCounterInfos;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java
new file mode 100644
index 000000000..18d3b391f
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java
@@ -0,0 +1,33 @@
+package com.didichuxing.doraemonkit.kit.timecounter.counter;
+
+import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo;
+
+/**
+ * @desc: App启动耗时
+ */
+public class AppCounter {
+
+ private long mStartTime;
+ private long mCost;
+ private CounterInfo mCounterInfo = new CounterInfo();
+
+ public void start() {
+ mStartTime = System.currentTimeMillis();
+ }
+
+ public void end() {
+ mCost = System.currentTimeMillis() - mStartTime;
+ mCounterInfo.title = "App Setup Cost";
+ mCounterInfo.totalCost = mCost;
+ mCounterInfo.type = CounterInfo.TYPE_APP;
+ mCounterInfo.time = System.currentTimeMillis();
+ }
+
+ public long getTime() {
+ return mCost;
+ }
+
+ public CounterInfo getAppSetupInfo() {
+ return mCounterInfo;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckDrawFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckDrawFloatPage.java
index b77a0b117..d34abcd97 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckDrawFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckDrawFloatPage.java
@@ -10,7 +10,7 @@
import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
-import com.didichuxing.doraemonkit.ui.viewcheck.ViewCheckRectView;
+import com.didichuxing.doraemonkit.ui.viewcheck.LayoutBorderView;
import com.didichuxing.doraemonkit.util.UIUtils;
/**
@@ -18,7 +18,7 @@
*/
public class ViewCheckDrawFloatPage extends BaseFloatPage implements ViewCheckFloatPage.OnViewSelectListener {
- private ViewCheckRectView mRectView;
+ private LayoutBorderView mLayoutBorderView;
@Override
protected void onCreate(Context context) {
@@ -31,12 +31,14 @@ protected void onCreate(Context context) {
protected void onDestroy() {
super.onDestroy();
ViewCheckFloatPage page = (ViewCheckFloatPage) FloatPageManager.getInstance().getFloatPage(PageTag.PAGE_VIEW_CHECK);
- page.removeViewSelectListener(this);
+ if (page != null) {
+ page.removeViewSelectListener(this);
+ }
}
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_view_check_draw, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_view_check_draw, null);
}
@Override
@@ -47,16 +49,28 @@ protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
@Override
protected void onViewCreated(View view) {
super.onViewCreated(view);
- mRectView = findViewById(R.id.rect_view);
+ mLayoutBorderView = findViewById(R.id.rect_view);
}
@Override
public void onViewSelected(View view) {
if (view == null) {
- mRectView.showViewRect(null);
+ mLayoutBorderView.showViewLayoutBorder(null);
} else {
- mRectView.showViewRect(UIUtils.getViewRect(view));
+ mLayoutBorderView.showViewLayoutBorder(UIUtils.getViewRect(view));
}
}
+
+ @Override
+ public void onEnterForeground() {
+ super.onEnterForeground();
+ getRootView().setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onEnterBackground() {
+ super.onEnterBackground();
+ getRootView().setVisibility(View.GONE);
+ }
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFloatPage.java
index 4248369c7..44947207d 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFloatPage.java
@@ -5,13 +5,13 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
+import com.didichuxing.doraemonkit.DoraemonKit;
import com.didichuxing.doraemonkit.R;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
-import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
import com.didichuxing.doraemonkit.util.LogHelper;
import com.didichuxing.doraemonkit.util.UIUtils;
@@ -22,25 +22,47 @@
* Created by wanglikun on 2018/11/20.
*/
-public class ViewCheckFloatPage extends BaseFloatPage implements View.OnTouchListener {
+public class ViewCheckFloatPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener {
private static final String TAG = "ViewCheckFloatPage";
- private float sdX, sdY;
- private float ldX, ldY;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
protected WindowManager mWindowManager;
private List mViewSelectListeners = new ArrayList<>();
+ private Activity mResumedActivity;
+
+ private DoraemonKit.ActivityLifecycleListener mLifecycleListener = new DoraemonKit.ActivityLifecycleListener() {
+ @Override
+ public void onActivityResumed(Activity activity) {
+ mResumedActivity = activity;
+ onViewSelected(null);
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+
+ }
+ };
+
@Override
protected void onCreate(Context context) {
super.onCreate(context);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mResumedActivity = DoraemonKit.getCurrentResumedActivity();
+ DoraemonKit.registerListener(mLifecycleListener);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ DoraemonKit.unRegisterListener(mLifecycleListener);
}
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_view_check, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_view_check, null);
}
@Override
@@ -55,25 +77,28 @@ protected void onLayoutParamsCreated(WindowManager.LayoutParams params) {
@Override
protected void onViewCreated(View view) {
super.onViewCreated(view);
- getRootView().setOnTouchListener(this);
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
}
private View findSelectView(int x, int y) {
- Activity resumedActivity = FloatPageManager.getInstance().getResumedActivity();
- if (resumedActivity == null) {
+ if (mResumedActivity == null) {
return null;
}
- if (resumedActivity.getWindow() == null) {
+ if (mResumedActivity.getWindow() == null) {
return null;
}
LogHelper.d(TAG, "x: " + x + ", y: " + y);
- y += UIUtils.getStatusBarHeight(getContext());
- return traverseViews(resumedActivity.getWindow().getDecorView(), x, y);
+ return traverseViews(mResumedActivity.getWindow().getDecorView(), x, y);
}
private View traverseViews(View view, int x, int y) {
int[] location = new int[2];
- view.getLocationOnScreen(location);
+ view.getLocationInWindow(location);
int left = location[0];
int top = location[1];
int right = left + view.getWidth();
@@ -88,7 +113,7 @@ private View traverseViews(View view, int x, int y) {
}
}
}
- if (left < x && x < right && top < y && y < bottom) {
+ if (left < x && x < right && top < y && y < bottom) {
return view;
} else {
return null;
@@ -96,7 +121,7 @@ private View traverseViews(View view, int x, int y) {
} else {
LogHelper.d(TAG, "class: " + view.getClass() + ", left: " + left
+ ", right: " + right + ", top: " + top + ", bottom: " + bottom);
- if (left < x && x < right && top < y && y < bottom) {
+ if (left < x && x < right && top < y && y < bottom) {
return view;
} else {
return null;
@@ -104,38 +129,6 @@ private View traverseViews(View view, int x, int y) {
}
}
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- float x = event.getRawX();
- float y = event.getRawY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- sdX = ldX = x;
- sdY = ldY = y;
- return false;
- case MotionEvent.ACTION_MOVE:
- getLayoutParams().x += (x - ldX + 0.5f);
- getLayoutParams().y += (y - ldY + 0.5f);
- ldX = x;
- ldY = y;
- mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
- return false;
- case MotionEvent.ACTION_UP:
- int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (Math.abs(x - sdX) <= mTouchSlop && Math.abs(y - sdY) <= mTouchSlop) {
- return false;
- }
- View selectView = findSelectView(getLayoutParams().x + getRootView().getWidth() / 2, getLayoutParams().y + getRootView().getHeight() / 2);
- for (OnViewSelectListener listener : mViewSelectListeners) {
- listener.onViewSelected(selectView);
- }
- return true;
- default:
- break;
- }
- return false;
- }
-
public void setViewSelectListener(OnViewSelectListener viewSelectListener) {
mViewSelectListeners.add(viewSelectListener);
}
@@ -144,7 +137,42 @@ public void removeViewSelectListener(OnViewSelectListener viewSelectListener) {
mViewSelectListeners.remove(viewSelectListener);
}
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+ View selectView = findSelectView(getLayoutParams().x + getRootView().getWidth() / 2, getLayoutParams().y + getRootView().getHeight() / 2);
+ onViewSelected(selectView);
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
+ }
+
+ private void onViewSelected(View view) {
+ for (OnViewSelectListener listener : mViewSelectListeners) {
+ listener.onViewSelected(view);
+ }
+ }
+
public interface OnViewSelectListener {
void onViewSelected(View view);
}
+ @Override
+ public void onEnterForeground() {
+ super.onEnterForeground();
+ getRootView().setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onEnterBackground() {
+ super.onEnterBackground();
+ getRootView().setVisibility(View.GONE);
+ }
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFragment.java
index 3466ab9cd..50ff19456 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckFragment.java
@@ -8,6 +8,7 @@
import android.view.View;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.ViewCheckConfig;
import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.ui.base.BaseFragment;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
@@ -27,7 +28,7 @@ public class ViewCheckFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_view_check;
+ return R.layout.dk_fragment_view_check;
}
@Override
@@ -63,10 +64,11 @@ public void onSettingItemSwitch(View view, SettingItem data, boolean on) {
FloatPageManager.getInstance().removeAll(ViewCheckInfoFloatPage.class);
FloatPageManager.getInstance().removeAll(ViewCheckFloatPage.class);
}
+ ViewCheckConfig.setViewCheckOpen(getContext(), on);
}
}
});
- mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_view_check, false));
+ mSettingItemAdapter.append(new SettingItem(R.string.dk_kit_view_check, ViewCheckConfig.isViewCheckOpen(getContext())));
mSettingList.setAdapter(mSettingItemAdapter);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckInfoFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckInfoFloatPage.java
index c30e4cffb..43ac5c863 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckInfoFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewCheckInfoFloatPage.java
@@ -1,37 +1,47 @@
package com.didichuxing.doraemonkit.kit.viewcheck;
+import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.AppCompatActivity;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
+import com.didichuxing.doraemonkit.DoraemonKit;
import com.didichuxing.doraemonkit.R;
+import com.didichuxing.doraemonkit.config.ViewCheckConfig;
import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
import com.didichuxing.doraemonkit.util.ColorUtil;
import com.didichuxing.doraemonkit.util.UIUtils;
+import java.util.List;
+
/**
* Created by wanglikun on 2018/11/23.
*/
-public class ViewCheckInfoFloatPage extends BaseFloatPage implements ViewCheckFloatPage.OnViewSelectListener, View.OnTouchListener {
+public class ViewCheckInfoFloatPage extends BaseFloatPage implements ViewCheckFloatPage.OnViewSelectListener, TouchProxy.OnTouchEventListener {
private TextView mName;
private TextView mId;
private TextView mPosition;
private TextView mDesc;
- private ImageView mClose;
+ private TextView mActivityInfo;
+ private TextView mFragmentInfo;
- private float sdX, sdY;
- private float ldX, ldY;
+ private ImageView mClose;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
private WindowManager mWindowManager;
@@ -47,31 +57,41 @@ protected void onCreate(Context context) {
protected void onDestroy() {
super.onDestroy();
ViewCheckFloatPage page = (ViewCheckFloatPage) FloatPageManager.getInstance().getFloatPage(PageTag.PAGE_VIEW_CHECK);
- page.removeViewSelectListener(this);
+ if (page != null) {
+ page.removeViewSelectListener(this);
+ }
}
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_view_check_info, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_view_check_info, null);
}
@Override
protected void onViewCreated(View view) {
super.onViewCreated(view);
mId = findViewById(R.id.id);
- mName= findViewById(R.id.name);
+ mName = findViewById(R.id.name);
mPosition = findViewById(R.id.position);
mDesc = findViewById(R.id.desc);
+ mActivityInfo = findViewById(R.id.activity);
+ mFragmentInfo = findViewById(R.id.fragment);
mClose = findViewById(R.id.close);
mClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ ViewCheckConfig.setViewCheckOpen(getContext(), false);
FloatPageManager.getInstance().removeAll(ViewCheckDrawFloatPage.class);
FloatPageManager.getInstance().removeAll(ViewCheckInfoFloatPage.class);
FloatPageManager.getInstance().removeAll(ViewCheckFloatPage.class);
}
});
- getRootView().setOnTouchListener(this);
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
}
@Override
@@ -104,34 +124,107 @@ public void onViewSelected(View view) {
}
String descText = getResources().getString(R.string.dk_view_check_info_desc, backgroundColor);
mDesc.setText(descText);
+ Activity activity = DoraemonKit.getCurrentResumedActivity();
+ if (activity != null) {
+ String activityText = activity.getClass().getSimpleName();
+ setTextAndVisible(mActivityInfo, getResources().getString(R.string.dk_view_check_info_activity, activityText));
+ String fragmentText = getVisibleFragment(activity);
+ if (!TextUtils.isEmpty(fragmentText)) {
+ setTextAndVisible(mFragmentInfo, getResources().getString(R.string.dk_view_check_info_fragment, fragmentText));
+ } else {
+ setTextAndVisible(mFragmentInfo, "");
+ }
+ } else {
+ setTextAndVisible(mActivityInfo, "");
+ setTextAndVisible(mFragmentInfo, "");
+ }
}
}
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- float x = event.getRawX();
- float y = event.getRawY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- sdX = ldX = x;
- sdY = ldY = y;
- return false;
- case MotionEvent.ACTION_MOVE:
- getLayoutParams().x += (x - ldX + 0.5f);
- getLayoutParams().y += (y - ldY + 0.5f);
- ldX = x;
- ldY = y;
- mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
- return false;
- case MotionEvent.ACTION_UP:
- int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (Math.abs(x - sdX) <= mTouchSlop && Math.abs(y - sdY) <= mTouchSlop) {
- return false;
+ private void setTextAndVisible(TextView textView, String text) {
+ if (TextUtils.isEmpty(text)) {
+ textView.setVisibility(View.GONE);
+ textView.setText("");
+ } else {
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(text);
+ }
+ }
+
+ private String getVisibleFragment(Activity activity) {
+ if (activity == null) {
+ return null;
+ }
+ StringBuilder builder = new StringBuilder();
+ if (activity instanceof AppCompatActivity) {
+ AppCompatActivity compatActivity = (AppCompatActivity) activity;
+ FragmentManager fragmentManager = compatActivity.getSupportFragmentManager();
+ List fragments = fragmentManager.getFragments();
+ if (fragments != null && fragments.size() != 0) {
+ for (int i = 0; i < fragments.size(); i++) {
+ Fragment fragment = fragments.get(i);
+ if (fragment != null && fragment.isVisible()) {
+ builder.append(fragment.getClass().getSimpleName() + "#" + fragment.getId());
+ if (i < fragments.size() - 1) {
+ builder.append(";");
+ }
+ }
}
- return true;
- default:
- break;
+ return builder.toString();
+ } else {
+ return getFragmentForActivity(activity);
+ }
+ } else {
+ return getFragmentForActivity(activity);
}
- return false;
+ }
+
+ private String getFragmentForActivity(Activity activity) {
+ StringBuilder builder = new StringBuilder();
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
+ android.app.FragmentManager manager = activity.getFragmentManager();
+ List list = manager.getFragments();
+ if (list != null && list.size() > 0) {
+ for (int i = 0; i < list.size(); i++) {
+ android.app.Fragment fragment = list.get(i);
+ if (fragment != null && fragment.isVisible()) {
+ builder.append(fragment.getClass().getSimpleName() + "#" + fragment.getId());
+ if (i < list.size() - 1) {
+ builder.append(";");
+ }
+ }
+ }
+ }
+ }
+ return builder.toString();
+ }
+
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
+ }
+
+ @Override
+ public void onEnterForeground() {
+ super.onEnterForeground();
+ getRootView().setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onEnterBackground() {
+ super.onEnterBackground();
+ getRootView().setVisibility(View.GONE);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewChecker.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewChecker.java
index 18b83c79e..57e2fc188 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewChecker.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/viewcheck/ViewChecker.java
@@ -1,14 +1,14 @@
package com.didichuxing.doraemonkit.kit.viewcheck;
import android.content.Context;
-import android.content.Intent;
import com.didichuxing.doraemonkit.R;
-import com.didichuxing.doraemonkit.constant.BundleKey;
-import com.didichuxing.doraemonkit.constant.FragmentIndex;
+import com.didichuxing.doraemonkit.config.ViewCheckConfig;
+import com.didichuxing.doraemonkit.constant.PageTag;
import com.didichuxing.doraemonkit.kit.Category;
import com.didichuxing.doraemonkit.kit.IKit;
-import com.didichuxing.doraemonkit.ui.UniversalActivity;
+import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
+import com.didichuxing.doraemonkit.ui.base.PageIntent;
/**
* Created by wanglikun on 2018/11/20.
@@ -32,14 +32,24 @@ public int getIcon() {
@Override
public void onClick(Context context) {
- Intent intent = new Intent(context, UniversalActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(BundleKey.FRAGMENT_INDEX, FragmentIndex.FRAGMENT_VIEW_CHECK);
- context.startActivity(intent);
+ PageIntent intent = new PageIntent(ViewCheckFloatPage.class);
+ intent.tag = PageTag.PAGE_VIEW_CHECK;
+ intent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(intent);
+
+ intent = new PageIntent(ViewCheckInfoFloatPage.class);
+ intent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(intent);
+
+ intent = new PageIntent(ViewCheckDrawFloatPage.class);
+ intent.mode = PageIntent.MODE_SINGLE_INSTANCE;
+ FloatPageManager.getInstance().add(intent);
+
+ ViewCheckConfig.setViewCheckOpen(context, true);
}
@Override
public void onAppInit(Context context) {
-
+ ViewCheckConfig.setViewCheckOpen(context, false);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorFragment.java
index 6ab2366bb..170364740 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorFragment.java
@@ -32,7 +32,7 @@ public class WebDoorFragment extends BaseFragment {
@Override
protected int onRequestLayout() {
- return R.layout.fragment_web_door;
+ return R.layout.dk_fragment_web_door;
}
@Override
@@ -97,7 +97,7 @@ private void doSearch(String url) {
return;
}
WebDoorManager.getInstance().saveHistory(getContext(), url);
- WebDoorManager.getInstance().getWebDoorCallback().overrideUrlLoading(url);
+ WebDoorManager.getInstance().getWebDoorCallback().overrideUrlLoading(getContext(), url);
mWebDoorHistoryAdapter.setData(WebDoorManager.getInstance().getHistory(getContext()));
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java
index 7e1536f9b..e0a513439 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/webdoor/WebDoorManager.java
@@ -68,6 +68,6 @@ public static WebDoorManager getInstance() {
}
public interface WebDoorCallback {
- void overrideUrlLoading(String url);
+ void overrideUrlLoading(Context context,String url);
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java
index e16ca9dcc..e4c3379f4 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java
@@ -4,7 +4,6 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -13,17 +12,17 @@
import com.didichuxing.doraemonkit.ui.base.BaseFloatPage;
import com.didichuxing.doraemonkit.ui.base.FloatPageManager;
import com.didichuxing.doraemonkit.ui.base.PageIntent;
+import com.didichuxing.doraemonkit.ui.base.TouchProxy;
/**
* 悬浮按钮
* Created by zhangweida on 2018/6/22.
*/
-public class FloatIconPage extends BaseFloatPage implements View.OnTouchListener {
+public class FloatIconPage extends BaseFloatPage implements TouchProxy.OnTouchEventListener {
protected WindowManager mWindowManager;
- private float sdX, sdY;
- private float ldX, ldY;
+ private TouchProxy mTouchProxy = new TouchProxy(this);
@Override
protected void onViewCreated(View view) {
@@ -35,12 +34,17 @@ public void onClick(View v) {
FloatPageManager.getInstance().add(pageIntent);
}
});
- getRootView().setOnTouchListener(this);
+ getRootView().setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mTouchProxy.onTouchEvent(v, event);
+ }
+ });
}
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_launch_icon, view, false);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_launch_icon, view, false);
}
@Override
@@ -57,36 +61,6 @@ protected void onCreate(Context context) {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- float x = event.getRawX();
- float y = event.getRawY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- sdX = ldX = x;
- sdY = ldY = y;
- return false;
- case MotionEvent.ACTION_MOVE:
- getLayoutParams().x += (x - ldX + 0.5f);
- getLayoutParams().y += (y - ldY + 0.5f);
- ldX = x;
- ldY = y;
- mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
- return false;
- case MotionEvent.ACTION_UP:
- FloatIconConfig.saveLastPosX(getContext(), getLayoutParams().x);
- FloatIconConfig.saveLastPosY(getContext(), getLayoutParams().y);
- int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (Math.abs(x - sdX) <= mTouchSlop && Math.abs(y - sdY) <= mTouchSlop) {
- return false;
- }
- return true;
- default:
- break;
- }
- return false;
- }
-
@Override
public void onEnterForeground() {
super.onEnterForeground();
@@ -98,4 +72,22 @@ public void onEnterBackground() {
super.onEnterBackground();
getRootView().setVisibility(View.GONE);
}
+
+ @Override
+ public void onMove(int x, int y, int dx, int dy) {
+ getLayoutParams().x += dx;
+ getLayoutParams().y += dy;
+ mWindowManager.updateViewLayout(getRootView(), getLayoutParams());
+ }
+
+ @Override
+ public void onUp(int x, int y) {
+ FloatIconConfig.saveLastPosX(getContext(), getLayoutParams().x);
+ FloatIconConfig.saveLastPosY(getContext(), getLayoutParams().y);
+ }
+
+ @Override
+ public void onDown(int x, int y) {
+
+ }
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/KitFloatPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/KitFloatPage.java
index 6663c3ece..e51a311c9 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/KitFloatPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/KitFloatPage.java
@@ -27,7 +27,7 @@ public class KitFloatPage extends BaseFloatPage{
@Override
protected View onCreateView(Context context, ViewGroup view) {
- return LayoutInflater.from(context).inflate(R.layout.float_kit, null);
+ return LayoutInflater.from(context).inflate(R.layout.dk_float_kit, null);
}
@Override
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/TranslucentActivity.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/TranslucentActivity.java
new file mode 100644
index 000000000..c1f9edffe
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/TranslucentActivity.java
@@ -0,0 +1,7 @@
+package com.didichuxing.doraemonkit.ui;
+
+/**
+ * 透明的容器activity
+ */
+public class TranslucentActivity extends UniversalActivity {
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/UniversalActivity.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/UniversalActivity.java
index f9e10086c..3d5fa44d4 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/UniversalActivity.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/UniversalActivity.java
@@ -9,16 +9,17 @@
import com.didichuxing.doraemonkit.kit.alignruler.AlignRulerSettingFragment;
import com.didichuxing.doraemonkit.kit.blockmonitor.BlockMonitorFragment;
import com.didichuxing.doraemonkit.kit.colorpick.ColorPickerSettingFragment;
-import com.didichuxing.doraemonkit.kit.cpu.CpuMainPageFragment;
import com.didichuxing.doraemonkit.kit.crash.CrashCaptureMainFragment;
import com.didichuxing.doraemonkit.kit.dataclean.DataCleanFragment;
import com.didichuxing.doraemonkit.kit.fileexplorer.FileExplorerFragment;
-import com.didichuxing.doraemonkit.kit.frameInfo.FrameInfoFragment;
import com.didichuxing.doraemonkit.kit.gpsmock.GpsMockFragment;
import com.didichuxing.doraemonkit.kit.logInfo.LogInfoSettingFragment;
import com.didichuxing.doraemonkit.kit.network.ui.NetWorkMonitorFragment;
-import com.didichuxing.doraemonkit.kit.ram.RamMainPageFragment;
+import com.didichuxing.doraemonkit.kit.parameter.cpu.CpuMainPageFragment;
+import com.didichuxing.doraemonkit.kit.parameter.frameInfo.FrameInfoFragment;
+import com.didichuxing.doraemonkit.kit.parameter.ram.RamMainPageFragment;
import com.didichuxing.doraemonkit.kit.sysinfo.SysInfoFragment;
+import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterFragment;
import com.didichuxing.doraemonkit.kit.viewcheck.ViewCheckFragment;
import com.didichuxing.doraemonkit.kit.webdoor.WebDoorFragment;
import com.didichuxing.doraemonkit.ui.base.BaseActivity;
@@ -45,42 +46,33 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
}
Class extends BaseFragment> fragmentClass = null;
switch (index) {
- case FragmentIndex.FRAGMENT_SYS_INFO: {
+ case FragmentIndex.FRAGMENT_SYS_INFO:
fragmentClass = SysInfoFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_FILE_EXPLORER: {
+ break;
+ case FragmentIndex.FRAGMENT_FILE_EXPLORER:
fragmentClass = FileExplorerFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_LOG_INFO_SETTING: {
+ break;
+ case FragmentIndex.FRAGMENT_LOG_INFO_SETTING:
fragmentClass = LogInfoSettingFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_COLOR_PICKER_SETTING: {
+ break;
+ case FragmentIndex.FRAGMENT_COLOR_PICKER_SETTING:
fragmentClass = ColorPickerSettingFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_FRAME_INFO: {
+ break;
+ case FragmentIndex.FRAGMENT_FRAME_INFO:
fragmentClass = FrameInfoFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_GPS_MOCK: {
+ break;
+ case FragmentIndex.FRAGMENT_GPS_MOCK:
fragmentClass = GpsMockFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_ALIGN_RULER_SETTING: {
+ break;
+ case FragmentIndex.FRAGMENT_ALIGN_RULER_SETTING:
fragmentClass = AlignRulerSettingFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_WEB_DOOR: {
+ break;
+ case FragmentIndex.FRAGMENT_WEB_DOOR:
fragmentClass = WebDoorFragment.class;
- }
- break;
- case FragmentIndex.FRAGMENT_DATA_CLEAN: {
+ break;
+ case FragmentIndex.FRAGMENT_DATA_CLEAN:
fragmentClass = DataCleanFragment.class;
- }
- break;
+ break;
case FragmentIndex.FRAGMENT_BLOCK_MONITOR:
fragmentClass = BlockMonitorFragment.class;
break;
@@ -99,6 +91,9 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
case FragmentIndex.FRAGMENT_RAM:
fragmentClass = RamMainPageFragment.class;
break;
+ case FragmentIndex.FRAGMENT_TIME_COUNTER:
+ fragmentClass = TimeCounterFragment.class;
+ break;
default:
break;
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/alignruler/AlignInfoView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/alignruler/AlignLineView.java
similarity index 91%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/alignruler/AlignInfoView.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/alignruler/AlignLineView.java
index e3708bf4d..7b70683ef 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/alignruler/AlignInfoView.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/alignruler/AlignLineView.java
@@ -13,24 +13,24 @@
* Created by wanglikun on 2018/12/4.
*/
-public class AlignInfoView extends View {
+public class AlignLineView extends View {
private Paint mTextPaint;
private Paint mLinePaint;
private int mPosX = -1;
private int mPosY = -1;
- public AlignInfoView(Context context) {
+ public AlignLineView(Context context) {
super(context);
init();
}
- public AlignInfoView(Context context, @Nullable AttributeSet attrs) {
+ public AlignLineView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
- public AlignInfoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ public AlignLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/BaseFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/BaseFragment.java
index 32c064e32..c138979f1 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/BaseFragment.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/BaseFragment.java
@@ -6,6 +6,7 @@
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -103,6 +104,10 @@ public void showToast(CharSequence msg) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
+ public void showToast(@StringRes int res) {
+ Toast.makeText(getContext(), res, Toast.LENGTH_SHORT).show();
+ }
+
public void showContent(Class extends BaseFragment> fragmentClass, Bundle bundle) {
BaseActivity activity = (BaseActivity) getActivity();
if (activity != null) {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/FloatPageManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/FloatPageManager.java
index 85133703b..05343a02c 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/FloatPageManager.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/FloatPageManager.java
@@ -22,8 +22,6 @@ public class FloatPageManager {
private Context mContext;
private List mPages = new ArrayList<>();
- private Activity mResumedActivity;
-
public void notifyBackground() {
for (BaseFloatPage page : mPages) {
page.onEnterBackground();
@@ -36,20 +34,6 @@ public void notifyForeground() {
}
}
- public void onActivityResumed(Activity activity) {
- mResumedActivity = activity;
- }
-
- public void onActivityPaused(Activity activity) {
- if (mResumedActivity == activity) {
- mResumedActivity = null;
- }
- }
-
- public Activity getResumedActivity() {
- return mResumedActivity;
- }
-
private static class Holder {
private static FloatPageManager INSTANCE = new FloatPageManager();
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/TouchProxy.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/TouchProxy.java
new file mode 100644
index 000000000..420bd840e
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/base/TouchProxy.java
@@ -0,0 +1,92 @@
+package com.didichuxing.doraemonkit.ui.base;
+
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.util.UIUtils;
+
+/**
+ * @author wanglikun
+ */
+public class TouchProxy {
+ private static final int MIN_DISTANCE_MOVE = 4;
+ private static final int MIN_TAP_TIME=1000;
+
+ private OnTouchEventListener mEventListener;
+ private int mLastX;
+ private int mLastY;
+ private int mStartX;
+ private int mStartY;
+ private TouchState mState = TouchState.STATE_STOP;
+
+ public TouchProxy(OnTouchEventListener eventListener) {
+ mEventListener = eventListener;
+ }
+
+ public void setEventListener(OnTouchEventListener eventListener) {
+ mEventListener = eventListener;
+ }
+
+ private enum TouchState {
+ STATE_MOVE,
+ STATE_STOP
+ }
+
+ public boolean onTouchEvent(View v, MotionEvent event) {
+ int distance= UIUtils.dp2px(v.getContext(),1)*MIN_DISTANCE_MOVE;
+ int x = (int) event.getRawX();
+ int y = (int) event.getRawY();
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN: {
+ mStartX = x;
+ mStartY = y;
+ mLastY = y;
+ mLastX = x;
+ if (mEventListener != null) {
+ mEventListener.onDown(x, y);
+ }
+ }
+ break;
+ case MotionEvent.ACTION_MOVE: {
+ if (Math.abs(x - mStartX) < distance
+ && Math.abs(y - mStartY) < distance) {
+ if (mState == TouchState.STATE_STOP) {
+ break;
+ }
+ } else if (mState != TouchState.STATE_MOVE){
+ mState = TouchState.STATE_MOVE;
+ }
+ if (mEventListener != null) {
+ mEventListener.onMove(mLastX, mLastY, x - mLastX, y - mLastY);
+ }
+ mLastY = y;
+ mLastX = x;
+ mState = TouchState.STATE_MOVE;
+ }
+ break;
+ case MotionEvent.ACTION_UP: {
+ if (mEventListener != null) {
+ mEventListener.onUp(x, y);
+ }
+ if (mState != TouchState.STATE_MOVE
+ &&event.getEventTime()-event.getDownTime()= 4) {
+ int alpha = Math.min(pixInterval * 36, 255);
+ mGridPaint.setAlpha(alpha);
+ mGridShadowPaint.setAlpha(alpha);
+ float value;
+ float start;
+ float end;
+ gridCanvas.save();
+ for (int i = 0; i <= getWidth(); i += pixInterval) {
+ value = (float) (i - 1);
+ start = 0f;
+ end = (float) height;
+ gridCanvas.drawLine(value, start, value, end, this.mGridPaint);
+ value = (float) i;
+ gridCanvas.drawLine(value, start, value, end, this.mGridShadowPaint);
+ }
+ for (int i = 0; i <= getHeight(); i += pixInterval) {
+ value = (float) (i - 1);
+ start = 0f;
+ end = (float) width;
+ gridCanvas.drawLine(start, value, end, value, this.mGridPaint);
+ value = (float) i;
+ gridCanvas.drawLine(start, value, end, value, this.mGridShadowPaint);
+ }
+ gridCanvas.restore();
+ }
+ return gridBitmap;
+ }
+
private void drawFocus(Canvas canvas) {
- float focusWidth = getResources().getDimensionPixelSize(R.dimen.dk_dp_6);
- canvas.drawRect(getWidth() / 2 - focusWidth / 2,
- getWidth() / 2 - focusWidth / 2,
- getWidth() / 2 + focusWidth / 2,
- getWidth() / 2 + focusWidth / 2,
+ float focusWidth = ColorPickConstants.PIX_INTERVAL + 4;
+ canvas.drawRect(getWidth() / 2 - 2,
+ getWidth() / 2 - 2,
+ getWidth() / 2 + focusWidth - 2,
+ getWidth() / 2 + focusWidth - 2,
mFocusPaint);
}
private void drawRing(Canvas canvas) {
- float ringWidth = getResources().getDimensionPixelSize(R.dimen.dk_dp_5);
+ canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
+ float ringWidth = ColorPickConstants.PIX_INTERVAL * 2 + 4;
- mRingPaint.setColor(getResources().getColor(R.color.dk_color_FFFFFF));
mRingPaint.setStrokeWidth(ringWidth);
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2 - ringWidth / 2, mRingPaint);
mRingPaint.setColor(getResources().getColor(R.color.dk_color_333333));
- mRingPaint.setStrokeWidth(1);
+ mRingPaint.setStrokeWidth(0.5f);
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, mRingPaint);
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2 - ringWidth, mRingPaint);
}
private void drawBitmap(Canvas canvas) {
- if (mDrawable == null) {
+ if (mCircleBitmap == null || mCircleBitmap.isRecycled()) {
return;
}
- mDrawable.draw(canvas);
+ canvas.save();
+ canvas.clipPath(mClipPath);
+ mBitmapMatrix.reset();
+ mBitmapMatrix.postScale(getWidth() / (float) mCircleBitmap.getWidth(), getHeight() / (float) mCircleBitmap.getHeight());
+ canvas.drawBitmap(mCircleBitmap, mBitmapMatrix, mBitmapPaint);
+ canvas.restore();
}
- public void setBitmap(Bitmap bitmap) {
- RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
- drawable.setBounds(0, 0, getRight(), getBottom());
- drawable.setCircular(true);
- mDrawable = drawable;
+ public void setBitmap(Bitmap bitmap, int color, int x, int y) {
+ mCircleBitmap = bitmap;
+ mText = String.format(ColorPickConstants.TEXT_FOCUS_INFO, ColorUtil.parseColorInt(color), x + ColorPickConstants.PIX_INTERVAL, y + ColorPickConstants.PIX_INTERVAL);
+ mRingPaint.setColor(color);
+ if (ColorUtil.isColdColor(color)) {
+ mFocusPaint.setColor(Color.WHITE);
+ mTextPaint.setColor(Color.WHITE);
+ } else {
+ mFocusPaint.setColor(Color.BLACK);
+ mTextPaint.setColor(Color.BLACK);
+ }
invalidate();
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java
index 48a37bd6e..3f9e6ff39 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java
@@ -36,7 +36,7 @@ public long getItemId(int position) {
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
- convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_crash_capture, parent, false);
+ convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.dk_item_crash_capture, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/FileInfoAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/FileInfoAdapter.java
index fd6a85c5d..421174f70 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/FileInfoAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/FileInfoAdapter.java
@@ -31,7 +31,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_file_info, parent, false);
+ return inflater.inflate(R.layout.dk_item_file_info, parent, false);
}
public class FileInfoViewHolder extends AbsViewBinder {
@@ -67,8 +67,11 @@ public boolean onLongClick(View v) {
mIcon.setImageResource(R.drawable.dk_jpg_icon);
} else if (FileUtil.getSuffix(fileInfo.file).equals(FileUtil.TXT)) {
mIcon.setImageResource(R.drawable.dk_txt_icon);
- } else {
+ } else if (FileUtil.getSuffix(fileInfo.file).equals(FileUtil.DB)){
+ mIcon.setImageResource(R.drawable.dk_file_db);
+ }else {
mIcon.setImageResource(R.drawable.dk_file_icon);
+
}
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/TextContentAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/TextContentAdapter.java
index 281130540..a9df58f6b 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/TextContentAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/fileexplorer/TextContentAdapter.java
@@ -27,7 +27,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_text_content, parent, false);
+ return inflater.inflate(R.layout.dk_item_text_content, parent, false);
}
private class TextContentViewHolder extends AbsViewBinder {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/frameinfo/PerformanceDataAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/frameinfo/PerformanceDataAdapter.java
index efb88a964..a7c7ebffe 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/frameinfo/PerformanceDataAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/frameinfo/PerformanceDataAdapter.java
@@ -25,7 +25,7 @@ protected AbsViewBinder createViewHolder(View view, int viewTyp
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_performance_detail, parent, false);
+ return inflater.inflate(R.layout.dk_item_performance_detail, parent, false);
}
public class PerformanceItemViewHolder extends AbsViewBinder {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/GroupKitAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/GroupKitAdapter.java
index 088a5e446..4ff765d8a 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/GroupKitAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/GroupKitAdapter.java
@@ -37,9 +37,9 @@ protected AbsViewBinder> createViewHolder(View view, int viewType)
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
if (viewType == Category.CLOSE) {
- return inflater.inflate(R.layout.item_close_kit, parent, false);
+ return inflater.inflate(R.layout.dk_item_close_kit, parent, false);
} else {
- return inflater.inflate(R.layout.item_group_kit, parent, false);
+ return inflater.inflate(R.layout.dk_item_group_kit, parent, false);
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/KitAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/KitAdapter.java
index 0237060ef..07507bbc4 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/KitAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/kit/KitAdapter.java
@@ -30,7 +30,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_kit, parent, false);
+ return inflater.inflate(R.layout.dk_item_kit, parent, false);
}
public class KitViewHolder extends AbsViewBinder {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ScalpelFrameLayout.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ScalpelFrameLayout.java
new file mode 100644
index 000000000..c73d7a558
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ScalpelFrameLayout.java
@@ -0,0 +1,499 @@
+package com.didichuxing.doraemonkit.ui.layoutborder;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.Camera;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
+
+import static android.graphics.Paint.ANTI_ALIAS_FLAG;
+import static android.graphics.Paint.Style.STROKE;
+import static android.graphics.Typeface.NORMAL;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_POINTER_UP;
+import static android.view.MotionEvent.INVALID_POINTER_ID;
+
+/**
+ * Renders your view hierarchy as an interactive 3D visualization of layers.
+ *
+ * Interactions supported:
+ *
+ * - Single touch: controls the rotation of the model.
+ * - Two finger vertical pinch: Adjust zoom.
+ * - Two finger horizontal pinch: Adjust layer spacing.
+ *
+ */
+public class ScalpelFrameLayout extends FrameLayout {
+ private static final int TRACKING_UNKNOWN = 0;
+ private static final int TRACKING_VERTICALLY = 1;
+ private static final int TRACKING_HORIZONTALLY = -1;
+ private static final int ROTATION_MAX = 60;
+ private static final int ROTATION_MIN = -ROTATION_MAX;
+ private static final int ROTATION_DEFAULT_X = -10;
+ private static final int ROTATION_DEFAULT_Y = 15;
+ private static final float ZOOM_DEFAULT = 0.6f;
+ private static final float ZOOM_MIN = 0.33f;
+ private static final float ZOOM_MAX = 2f;
+ private static final int SPACING_DEFAULT = 25;
+ private static final int SPACING_MIN = 10;
+ private static final int SPACING_MAX = 100;
+ private static final int CHROME_COLOR = 0xFF888888;
+ private static final int CHROME_SHADOW_COLOR = 0xFF000000;
+ private static final int TEXT_OFFSET_DP = 2;
+ private static final int TEXT_SIZE_DP = 10;
+ private static final int CHILD_COUNT_ESTIMATION = 25;
+ private static final boolean DEBUG = false;
+
+ private static void log(String message, Object... args) {
+ Log.d("Scalpel", String.format(message, args));
+ }
+
+ private static class LayeredView {
+ View view;
+ int layer;
+
+ void set(View view, int layer) {
+ this.view = view;
+ this.layer = layer;
+ }
+
+ void clear() {
+ view = null;
+ layer = -1;
+ }
+ }
+
+ private final Rect viewBoundsRect = new Rect();
+ private final Paint viewBorderPaint = new Paint(ANTI_ALIAS_FLAG);
+ private final Camera camera = new Camera();
+ private final Matrix matrix = new Matrix();
+ private final int[] location = new int[2];
+ private final BitSet visibilities = new BitSet(CHILD_COUNT_ESTIMATION);
+ private final SparseArray idNames = new SparseArray<>();
+ private final Deque layeredViewQueue = new ArrayDeque<>();
+ private final Pool layeredViewPool = new Pool(CHILD_COUNT_ESTIMATION) {
+ @Override protected LayeredView newObject() {
+ return new LayeredView();
+ }
+ };
+
+ private final Resources res;
+ private final float density;
+ private final float slop;
+ private final float textOffset;
+ private final float textSize;
+
+ private boolean enabled;
+ private boolean drawViews = true;
+ private boolean drawIds;
+
+ private int pointerOne = INVALID_POINTER_ID;
+ private float lastOneX;
+ private float lastOneY;
+ private int pointerTwo = INVALID_POINTER_ID;
+ private float lastTwoX;
+ private float lastTwoY;
+ private int multiTouchTracking = TRACKING_UNKNOWN;
+
+ private float rotationY = ROTATION_DEFAULT_Y;
+ private float rotationX = ROTATION_DEFAULT_X;
+ private float zoom = ZOOM_DEFAULT;
+ private float spacing = SPACING_DEFAULT;
+
+ private int chromeColor;
+ private int chromeShadowColor;
+
+ public ScalpelFrameLayout(Context context) {
+ this(context, null);
+ }
+
+ public ScalpelFrameLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ScalpelFrameLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ res = context.getResources();
+ density = context.getResources().getDisplayMetrics().density;
+ slop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+ textSize = TEXT_SIZE_DP * density;
+ textOffset = TEXT_OFFSET_DP * density;
+
+ setChromeColor(CHROME_COLOR);
+ viewBorderPaint.setStyle(STROKE);
+ viewBorderPaint.setTextSize(textSize);
+ setChromeShadowColor(CHROME_SHADOW_COLOR);
+ if (Build.VERSION.SDK_INT >= JELLY_BEAN) {
+ viewBorderPaint.setTypeface(Typeface.create("sans-serif-condensed", NORMAL));
+ }
+ }
+
+ /** Set the view border chrome color. */
+ public void setChromeColor(int color) {
+ if (chromeColor != color) {
+ viewBorderPaint.setColor(color);
+ chromeColor = color;
+ invalidate();
+ }
+ }
+
+ /** Get the view border chrome color. */
+ public int getChromeColor() {
+ return chromeColor;
+ }
+
+ /** Set the view border chrome shadow color. */
+ public void setChromeShadowColor(int color) {
+ if (chromeShadowColor != color) {
+ viewBorderPaint.setShadowLayer(1, -1, 1, color);
+ chromeShadowColor = color;
+ invalidate();
+ }
+ }
+
+ /** Get the view border chrome shadow color. */
+ public int getChromeShadowColor() {
+ return chromeShadowColor;
+ }
+
+ /** Set whether or not the 3D view layer interaction is enabled. */
+ public void setLayerInteractionEnabled(boolean enabled) {
+ if (this.enabled != enabled) {
+ this.enabled = enabled;
+ setWillNotDraw(!enabled);
+ invalidate();
+ }
+ }
+
+ /** Returns true when 3D view layer interaction is enabled. */
+ public boolean isLayerInteractionEnabled() {
+ return enabled;
+ }
+
+ /** Set whether the view layers draw their contents. When false, only wireframes are shown. */
+ public void setDrawViews(boolean drawViews) {
+ if (this.drawViews != drawViews) {
+ this.drawViews = drawViews;
+ invalidate();
+ }
+ }
+
+ /** Returns true when view layers draw their contents. */
+ public boolean isDrawingViews() {
+ return drawViews;
+ }
+
+ /** Set whether the view layers draw their IDs. */
+ public void setDrawIds(boolean drawIds) {
+ if (this.drawIds != drawIds) {
+ this.drawIds = drawIds;
+ invalidate();
+ }
+ }
+
+ /** Returns true when view layers draw their IDs. */
+ public boolean isDrawingIds() {
+ return drawIds;
+ }
+
+ @Override public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return enabled || super.onInterceptTouchEvent(ev);
+ }
+
+ @Override public boolean onTouchEvent(@SuppressWarnings("NullableProblems") MotionEvent event) {
+ if (!enabled) {
+ return super.onTouchEvent(event);
+ }
+
+ int action = event.getActionMasked();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ int index = (action == ACTION_DOWN) ? 0 : event.getActionIndex();
+ if (pointerOne == INVALID_POINTER_ID) {
+ pointerOne = event.getPointerId(index);
+ lastOneX = event.getX(index);
+ lastOneY = event.getY(index);
+ if (DEBUG) log("Got pointer 1! id: %s x: %s y: %s", pointerOne, lastOneY, lastOneY);
+ } else if (pointerTwo == INVALID_POINTER_ID) {
+ pointerTwo = event.getPointerId(index);
+ lastTwoX = event.getX(index);
+ lastTwoY = event.getY(index);
+ if (DEBUG) log("Got pointer 2! id: %s x: %s y: %s", pointerTwo, lastTwoY, lastTwoY);
+ } else {
+ if (DEBUG) log("Ignoring additional pointer. id: %s", event.getPointerId(index));
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_MOVE: {
+ if (pointerTwo == INVALID_POINTER_ID) {
+ // Single pointer controlling 3D rotation.
+ for (int i = 0, count = event.getPointerCount(); i < count; i++) {
+ if (pointerOne == event.getPointerId(i)) {
+ float eventX = event.getX(i);
+ float eventY = event.getY(i);
+ float dx = eventX - lastOneX;
+ float dy = eventY - lastOneY;
+ float drx = 90 * (dx / getWidth());
+ float dry = 90 * (-dy / getHeight()); // Invert Y-axis.
+ // An 'x' delta affects 'y' rotation and vise versa.
+ rotationY = Math.min(Math.max(rotationY + drx, ROTATION_MIN), ROTATION_MAX);
+ rotationX = Math.min(Math.max(rotationX + dry, ROTATION_MIN), ROTATION_MAX);
+ if (DEBUG) {
+ log("Single pointer moved (%s, %s) affecting rotation (%s, %s).", dx, dy, drx, dry);
+ }
+
+ lastOneX = eventX;
+ lastOneY = eventY;
+
+ invalidate();
+ }
+ }
+ } else {
+ // We know there's two pointers and we only care about pointerOne and pointerTwo
+ int pointerOneIndex = event.findPointerIndex(pointerOne);
+ int pointerTwoIndex = event.findPointerIndex(pointerTwo);
+
+ float xOne = event.getX(pointerOneIndex);
+ float yOne = event.getY(pointerOneIndex);
+ float xTwo = event.getX(pointerTwoIndex);
+ float yTwo = event.getY(pointerTwoIndex);
+
+ float dxOne = xOne - lastOneX;
+ float dyOne = yOne - lastOneY;
+ float dxTwo = xTwo - lastTwoX;
+ float dyTwo = yTwo - lastTwoY;
+
+ if (multiTouchTracking == TRACKING_UNKNOWN) {
+ float adx = Math.abs(dxOne) + Math.abs(dxTwo);
+ float ady = Math.abs(dyOne) + Math.abs(dyTwo);
+
+ if (adx > slop * 2 || ady > slop * 2) {
+ if (adx > ady) {
+ // Left/right movement wins. Track horizontal.
+ multiTouchTracking = TRACKING_HORIZONTALLY;
+ } else {
+ // Up/down movement wins. Track vertical.
+ multiTouchTracking = TRACKING_VERTICALLY;
+ }
+ }
+ }
+
+ if (multiTouchTracking == TRACKING_VERTICALLY) {
+ if (yOne >= yTwo) {
+ zoom += dyOne / getHeight() - dyTwo / getHeight();
+ } else {
+ zoom += dyTwo / getHeight() - dyOne / getHeight();
+ }
+
+ zoom = Math.min(Math.max(zoom, ZOOM_MIN), ZOOM_MAX);
+ invalidate();
+ } else if (multiTouchTracking == TRACKING_HORIZONTALLY) {
+ if (xOne >= xTwo) {
+ spacing += (dxOne / getWidth() * SPACING_MAX) - (dxTwo / getWidth() * SPACING_MAX);
+ } else {
+ spacing += (dxTwo / getWidth() * SPACING_MAX) - (dxOne / getWidth() * SPACING_MAX);
+ }
+
+ spacing = Math.min(Math.max(spacing, SPACING_MIN), SPACING_MAX);
+ invalidate();
+ }
+
+ if (multiTouchTracking != TRACKING_UNKNOWN) {
+ lastOneX = xOne;
+ lastOneY = yOne;
+ lastTwoX = xTwo;
+ lastTwoY = yTwo;
+ }
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP: {
+ int index = (action != ACTION_POINTER_UP) ? 0 : event.getActionIndex();
+ int pointerId = event.getPointerId(index);
+ if (pointerOne == pointerId) {
+ // Shift pointer two (real or invalid) up to pointer one.
+ pointerOne = pointerTwo;
+ lastOneX = lastTwoX;
+ lastOneY = lastTwoY;
+ if (DEBUG) log("Promoting pointer 2 (%s) to pointer 1.", pointerTwo);
+ // Clear pointer two and tracking.
+ pointerTwo = INVALID_POINTER_ID;
+ multiTouchTracking = TRACKING_UNKNOWN;
+ } else if (pointerTwo == pointerId) {
+ if (DEBUG) log("Lost pointer 2 (%s).", pointerTwo);
+ pointerTwo = INVALID_POINTER_ID;
+ multiTouchTracking = TRACKING_UNKNOWN;
+ }
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ @Override public void draw(@SuppressWarnings("NullableProblems") Canvas canvas) {
+ if (!enabled) {
+ super.draw(canvas);
+ return;
+ }
+
+ getLocationInWindow(location);
+ float x = location[0];
+ float y = location[1];
+
+ int saveCount = canvas.save();
+
+ float cx = getWidth() / 2f;
+ float cy = getHeight() / 2f;
+
+ camera.save();
+ camera.rotate(rotationX, rotationY, 0);
+ camera.getMatrix(matrix);
+ camera.restore();
+
+ matrix.preTranslate(-cx, -cy);
+ matrix.postTranslate(cx, cy);
+ canvas.concat(matrix);
+ canvas.scale(zoom, zoom, cx, cy);
+
+ if (!layeredViewQueue.isEmpty()) {
+ throw new AssertionError("View queue is not empty.");
+ }
+
+ // We don't want to be rendered so seed the queue with our children.
+ for (int i = 0, count = getChildCount(); i < count; i++) {
+ LayeredView layeredView = layeredViewPool.obtain();
+ layeredView.set(getChildAt(i), 0);
+ layeredViewQueue.add(layeredView);
+ }
+
+ while (!layeredViewQueue.isEmpty()) {
+ LayeredView layeredView = layeredViewQueue.removeFirst();
+ View view = layeredView.view;
+ int layer = layeredView.layer;
+
+ // Restore the object to the pool for use later.
+ layeredView.clear();
+ layeredViewPool.restore(layeredView);
+
+ // Hide any visible children.
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ visibilities.clear();
+ for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
+ View child = viewGroup.getChildAt(i);
+ //noinspection ConstantConditions
+ if (child.getVisibility() == VISIBLE) {
+ visibilities.set(i);
+ child.setVisibility(INVISIBLE);
+ }
+ }
+ }
+
+ int viewSaveCount = canvas.save();
+
+ // Scale the layer index translation by the rotation amount.
+ float translateShowX = rotationY / ROTATION_MAX;
+ float translateShowY = rotationX / ROTATION_MAX;
+ float tx = layer * spacing * density * translateShowX;
+ float ty = layer * spacing * density * translateShowY;
+ canvas.translate(tx, -ty);
+
+ view.getLocationInWindow(location);
+ canvas.translate(location[0] - x, location[1] - y);
+
+ viewBoundsRect.set(0, 0, view.getWidth(), view.getHeight());
+ canvas.drawRect(viewBoundsRect, viewBorderPaint);
+
+ if (drawViews) {
+ if (!(view instanceof SurfaceView)) {
+ view.draw(canvas);
+ }
+ }
+
+ if (drawIds) {
+ int id = view.getId();
+ if (id != NO_ID) {
+ canvas.drawText(nameForId(id), textOffset, textSize, viewBorderPaint);
+ }
+ }
+
+ canvas.restoreToCount(viewSaveCount);
+
+ // Restore any hidden children and queue them for later drawing.
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
+ if (visibilities.get(i)) {
+ View child = viewGroup.getChildAt(i);
+ //noinspection ConstantConditions
+ child.setVisibility(VISIBLE);
+ LayeredView childLayeredView = layeredViewPool.obtain();
+ childLayeredView.set(child, layer + 1);
+ layeredViewQueue.add(childLayeredView);
+ }
+ }
+ }
+ }
+
+ canvas.restoreToCount(saveCount);
+ }
+
+ private String nameForId(int id) {
+ String name = idNames.get(id);
+ if (name == null) {
+ try {
+ name = res.getResourceEntryName(id);
+ } catch (NotFoundException e) {
+ name = String.format("0x%8x", id);
+ }
+ idNames.put(id, name);
+ }
+ return name;
+ }
+
+ private static abstract class Pool {
+ private final Deque pool;
+
+ Pool(int initialSize) {
+ pool = new ArrayDeque<>(initialSize);
+ for (int i = 0; i < initialSize; i++) {
+ pool.addLast(newObject());
+ }
+ }
+
+ T obtain() {
+ return pool.isEmpty() ? newObject() : pool.removeLast();
+ }
+
+ void restore(T instance) {
+ pool.addLast(instance);
+ }
+
+ protected abstract T newObject();
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ViewBorderDrawable.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ViewBorderDrawable.java
new file mode 100644
index 000000000..3b713fc8d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ViewBorderDrawable.java
@@ -0,0 +1,60 @@
+package com.didichuxing.doraemonkit.ui.layoutborder;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import com.didichuxing.doraemonkit.config.LayoutBorderConfig;
+
+/**
+ * Created by wanglikun on 2019/1/11
+ */
+public class ViewBorderDrawable extends Drawable {
+ private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ private final Rect rect;
+
+ private final Context context;
+
+ public ViewBorderDrawable(View view) {
+ rect = new Rect(0, 0, view.getWidth(), view.getHeight());
+ context= view.getContext();
+
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setColor(Color.RED);
+ paint.setStrokeWidth(2);
+ paint.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0));
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ if (LayoutBorderConfig.isLayoutBorderOpen()) {
+ canvas.drawRect(rect, paint);
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ // to be safe
+ return PixelFormat.TRANSLUCENT;
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ViewBorderFrameLayout.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ViewBorderFrameLayout.java
new file mode 100644
index 000000000..67dc128ea
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/layoutborder/ViewBorderFrameLayout.java
@@ -0,0 +1,126 @@
+package com.didichuxing.doraemonkit.ui.layoutborder;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.SurfaceView;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.didichuxing.doraemonkit.config.LayoutBorderConfig;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by wanglikun on 2019/1/12
+ */
+public class ViewBorderFrameLayout extends FrameLayout {
+ public ViewBorderFrameLayout(@NonNull Context context) {
+ super(context);
+ }
+
+ public ViewBorderFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ViewBorderFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (LayoutBorderConfig.isLayoutBorderOpen()) {
+ traverseChild(this);
+ } else {
+ clearChild(this);
+ }
+ }
+
+ private void traverseChild(View view) {
+ if (view instanceof ViewGroup) {
+ replaceDrawable(view);
+ int childCount = ((ViewGroup) view).getChildCount();
+ if (childCount != 0) {
+ for (int index = 0; index < childCount; index++) {
+ traverseChild(((ViewGroup) view).getChildAt(index));
+ }
+ }
+ } else {
+ replaceDrawable(view);
+ }
+ }
+
+ private void replaceDrawable(View view) {
+ if (view instanceof TextureView) {
+ // 过滤TextureView
+ return;
+ }
+ LayerDrawable newDrawable;
+ if (view.getBackground() != null) {
+ Drawable oldDrawable = view.getBackground();
+ if (oldDrawable instanceof LayerDrawable) {
+ for (int i = 0; i < ((LayerDrawable) oldDrawable).getNumberOfLayers(); i++) {
+ if (((LayerDrawable) oldDrawable).getDrawable(i) instanceof ViewBorderDrawable) {
+ // already replace
+ return;
+ }
+ }
+ newDrawable = new LayerDrawable(new Drawable[]{
+ oldDrawable,
+ new ViewBorderDrawable(view)
+ });
+ } else {
+ newDrawable = new LayerDrawable(new Drawable[]{
+ oldDrawable,
+ new ViewBorderDrawable(view)
+ });
+ }
+ } else {
+ newDrawable = new LayerDrawable(new Drawable[]{
+ new ViewBorderDrawable(view)
+ });
+ }
+ view.setBackground(newDrawable);
+ }
+
+ private void clearChild(View view) {
+ if (view instanceof ViewGroup) {
+ clearDrawable(view);
+ int childCount = ((ViewGroup) view).getChildCount();
+ if (childCount != 0) {
+ for (int index = 0; index < childCount; index++) {
+ clearChild(((ViewGroup) view).getChildAt(index));
+ }
+ }
+ } else {
+ clearDrawable(view);
+ }
+ }
+
+ private void clearDrawable(View view) {
+ if (view.getBackground() == null) {
+ return;
+ }
+ Drawable oldDrawable = view.getBackground();
+ if (!(oldDrawable instanceof LayerDrawable)) {
+ return;
+ }
+ LayerDrawable layerDrawable = (LayerDrawable) oldDrawable;
+ List drawables = new ArrayList<>();
+ for (int i = 0; i < layerDrawable.getNumberOfLayers(); i++) {
+ if (layerDrawable.getDrawable(i) instanceof ViewBorderDrawable) {
+ continue;
+ }
+ drawables.add(layerDrawable.getDrawable(i));
+ }
+ LayerDrawable newDrawable = new LayerDrawable(drawables.toArray(new Drawable[drawables.size()]));
+ view.setBackground(newDrawable);
+ }
+}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/loginfo/LogItemAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/loginfo/LogItemAdapter.java
index 384754a12..ab69fb593 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/loginfo/LogItemAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/loginfo/LogItemAdapter.java
@@ -31,7 +31,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_log, parent, false);
+ return inflater.inflate(R.layout.dk_item_log, parent, false);
}
public class LogInfoViewHolder extends AbsViewBinder {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartIconPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartIconPage.java
index 1aec8b4aa..c5758da5a 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartIconPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartIconPage.java
@@ -56,21 +56,6 @@ public void setListener(OnFloatPageChangeListener listener) {
mListener = listener;
}
- @Override
- protected boolean onBackPressed() {
- return false;
- }
-
- @Override
- public void onHomeKeyPress() {
- finish();
- }
-
- @Override
- public void onRecentAppKeyPress() {
- finish();
- }
-
protected static void openChartIconPage(int type, OnFloatPageChangeListener listener) {
FloatPageManager.getInstance().remove(RealTimeChartIconPage.TAG);
PageIntent pageIntent = new PageIntent(RealTimeChartIconPage.class);
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartPage.java
index 4c87a2ee1..dd24321aa 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartPage.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/RealTimeChartPage.java
@@ -63,25 +63,6 @@ protected boolean onBackPressed() {
return false;
}
- @Override
- public void onHomeKeyPress() {
- finish();
- mLineChart.stopMove();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mLineChart.stopMove();
- }
-
- @Override
- public void onRecentAppKeyPress() {
- finish();
- mLineChart.stopMove();
- }
-
-
/**
* 打开实时折线图浮窗
*
@@ -150,14 +131,14 @@ public static void removeCloseListener() {
@Override
public void onEnterForeground() {
super.onEnterForeground();
+ mLineChart.startMove();
getRootView().setVisibility(View.VISIBLE);
}
@Override
public void onEnterBackground() {
super.onEnterBackground();
+ mLineChart.stopMove();
getRootView().setVisibility(View.GONE);
}
-
-
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/MemoryDataSource.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/MemoryDataSource.java
index f6fe8bae8..6b4143b3e 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/MemoryDataSource.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/MemoryDataSource.java
@@ -4,9 +4,15 @@
import com.didichuxing.doraemonkit.ui.realtime.widget.LineChart;
public class MemoryDataSource implements IDataSource {
+ private float mMaxRam;
+
+ public MemoryDataSource() {
+ mMaxRam = (float) (Runtime.getRuntime().maxMemory() * 1.0 / (1024 * 1024));
+ }
+
@Override
public LineChart.LineData createData() {
float info = PerformanceDataManager.getInstance().getLastMemoryInfo();
- return LineChart.LineData.obtain(info, Math.round(info) + "MB");
+ return LineChart.LineData.obtain(info / mMaxRam * 100, Math.round(info) + "MB");
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/NetworkDataSource.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/NetworkDataSource.java
index d545bc1be..9cefc5625 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/NetworkDataSource.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/datasource/NetworkDataSource.java
@@ -22,9 +22,9 @@ public LineChart.LineData createData() {
}
latestTotalLength = totalSize;
if (diff == 0) {
- return LineChart.LineData.obtain(diff / 10, null);
+ return LineChart.LineData.obtain((float) Math.ceil(diff / 1024f), null);
} else {
- return LineChart.LineData.obtain(diff / 10, ByteUtil.getPrintSize(diff));
+ return LineChart.LineData.obtain((float) Math.ceil(diff / 1024f), ByteUtil.getPrintSize(diff));
}
}
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/widget/LineChart.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/widget/LineChart.java
index 2989c7119..f016749a8 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/widget/LineChart.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/realtime/widget/LineChart.java
@@ -29,7 +29,7 @@ public LineChart(@NonNull Context context, @Nullable AttributeSet attrs) {
}
private void initView(Context context) {
- inflate(context, R.layout.view_line_chart, this);
+ inflate(context, R.layout.dk_view_line_chart, this);
mTitle = findViewById(R.id.tv_title);
mLine = findViewById(R.id.line_chart_view);
}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/setting/SettingItemAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/setting/SettingItemAdapter.java
index ee699b235..49c878a32 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/setting/SettingItemAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/setting/SettingItemAdapter.java
@@ -32,7 +32,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_setting, parent, false);
+ return inflater.inflate(R.layout.dk_item_setting, parent, false);
}
public class SettingItemViewHolder extends AbsViewBinder {
@@ -56,6 +56,7 @@ public void bind(final SettingItem settingItem) {
mDesc.setText(settingItem.desc);
if (settingItem.canCheck) {
mMenuSwitch.setVisibility(View.VISIBLE);
+ mMenuSwitch.setChecked(settingItem.isChecked);
mMenuSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -63,7 +64,6 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mOnSettingItemSwitchListener.onSettingItemSwitch(mMenuSwitch, settingItem, isChecked);
}
});
- mMenuSwitch.setChecked(settingItem.isChecked);
}
if (settingItem.icon != 0) {
mIcon.setVisibility(View.VISIBLE);
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/viewcheck/ViewCheckRectView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/viewcheck/LayoutBorderView.java
similarity index 56%
rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/viewcheck/ViewCheckRectView.java
rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/viewcheck/LayoutBorderView.java
index 3e9e1274e..9e8770bfc 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/viewcheck/ViewCheckRectView.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/viewcheck/LayoutBorderView.java
@@ -10,25 +10,28 @@
import android.util.AttributeSet;
import android.view.View;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Created by wanglikun on 2018/11/23.
*/
-public class ViewCheckRectView extends View {
+public class LayoutBorderView extends View {
private Paint mRectPaint;
- private Rect mRect;
+ private List mRects = new ArrayList<>();
- public ViewCheckRectView(Context context) {
+ public LayoutBorderView(Context context) {
super(context);
initView();
}
- public ViewCheckRectView(Context context, @Nullable AttributeSet attrs) {
+ public LayoutBorderView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
- public ViewCheckRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ public LayoutBorderView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@@ -43,17 +46,26 @@ private void initView() {
@Override
protected void onDraw(Canvas canvas) {
- if (mRect != null) {
- canvas.drawRect(mRect, mRectPaint);
+ for (Rect rect : mRects) {
+ canvas.drawRect(rect, mRectPaint);
+ }
+ }
+
+ public void showViewLayoutBorder(Rect rect) {
+ mRects.clear();
+ if (rect != null) {
+ mRects.add(rect);
}
+
+ invalidate();
}
- public void showViewRect(Rect rect) {
- if (rect == null) {
- mRect = null;
- } else {
- mRect = new Rect(rect);
+ public void showViewLayoutBorders(List rects) {
+ if (rects == null) {
+ return;
}
+ mRects.clear();
+ mRects.addAll(rects);
invalidate();
}
}
\ No newline at end of file
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/webdoor/WebDoorHistoryAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/webdoor/WebDoorHistoryAdapter.java
index b3b8709e2..8a36c92b7 100644
--- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/webdoor/WebDoorHistoryAdapter.java
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/webdoor/WebDoorHistoryAdapter.java
@@ -28,7 +28,7 @@ protected AbsViewBinder createViewHolder(View view, int viewType) {
@Override
protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) {
- return inflater.inflate(R.layout.item_web_door_history, parent, false);
+ return inflater.inflate(R.layout.dk_item_web_door_history, parent, false);
}
public class WebDoorHistoryViewHolder extends AbsViewBinder {
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/SelectionOperation.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/SelectionOperation.java
new file mode 100755
index 000000000..e4c1a63dd
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/SelectionOperation.java
@@ -0,0 +1,73 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ISelectFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.MatrixHelper;
+
+
+public class SelectionOperation implements MatrixHelper.OnInterceptListener {
+ /**
+ * 选中区域
+ */
+ private static final int INVALID = -1; //无效坐标
+ private Rect selectionRect;
+ private ISelectFormat selectFormat;
+ private int selectRow = INVALID;
+ private int selectColumn = INVALID;
+ private boolean isShow;
+
+ public void reset() {
+ isShow = false;
+ }
+
+ public SelectionOperation() {
+ this.selectionRect = new Rect();
+ }
+
+ public void setSelectionRect(int selectColumn, int selectRow, Rect rect) {
+ this.selectRow = selectRow;
+ this.selectColumn = selectColumn;
+ selectionRect.set(rect);
+ isShow = true;
+ }
+
+ public boolean isSelectedPoint(int selectColumn, int selectRow) {
+
+ return selectRow == this.selectRow && selectColumn == this.selectColumn;
+ }
+
+ public void checkSelectedPoint(int selectColumn, int selectRow, Rect rect) {
+
+ if (isSelectedPoint(selectColumn, selectRow)) {
+
+ selectionRect.set(rect);
+ isShow = true;
+ }
+ }
+
+
+ public void draw(Canvas canvas, Rect showRect, TableConfig config) {
+
+ if (selectFormat != null && isShow) {
+ selectFormat.draw(canvas, selectionRect, showRect, config);
+ }
+ }
+
+ public ISelectFormat getSelectFormat() {
+ return selectFormat;
+ }
+
+ public void setSelectFormat(ISelectFormat selectFormat) {
+ this.selectFormat = selectFormat;
+ }
+
+ @Override
+ public boolean isIntercept(MotionEvent e1, float distanceX, float distanceY) {
+ return false;
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableConfig.java
new file mode 100755
index 000000000..2986dd079
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableConfig.java
@@ -0,0 +1,281 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview;
+
+import android.graphics.Paint;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.style.FontStyle;
+import com.didichuxing.doraemonkit.ui.widget.tableview.style.LineStyle;
+
+
+public class TableConfig {
+ /**
+ * 默认字体样式
+ */
+ private static final FontStyle defaultFontStyle = new FontStyle();
+ /**
+ * 默认网格样式
+ */
+ private static final LineStyle defaultGridStyle = new LineStyle();
+ /**
+ * 无效值
+ */
+ public static final int INVALID_COLOR = 0;
+ /**
+ * 内容字体样式
+ */
+ public FontStyle contentStyle = defaultFontStyle;
+ /**
+ * 左侧序号列字体样式
+ */
+ public FontStyle YSequenceStyle = defaultFontStyle;
+ /**
+ * 列标题字体样式
+ */
+ public FontStyle columnTitleStyle = defaultFontStyle;
+ /**
+ * 表格标题字体样式
+ */
+ public FontStyle tableTitleStyle = defaultFontStyle;
+ /**
+ * 列标题网格样式
+ */
+ public LineStyle columnTitleGridStyle = defaultGridStyle;
+ /**
+ * 序列网格样式
+ */
+ public LineStyle SequenceGridStyle = defaultGridStyle;
+ /**
+ * 表格网格
+ */
+ public LineStyle contentGridStyle = defaultGridStyle;
+ /**
+ * 上下padding(为了表格的美观,暂只支持统一的padding)
+ */
+ private int verticalPadding = 10;
+ /**
+ * 文字左边偏移
+ */
+ private int textLeftOffset = 0;
+ /**
+ * 增加列序列左右padding
+ */
+ private int sequenceHorizontalPadding = 40;
+
+ /**
+ * 增加列标题上下padding
+ */
+ private int columnTitleVerticalPadding = 10;
+ /**
+ * 增加列标题左右padding
+ */
+ private int columnTitleHorizontalPadding = 40;
+ /**
+ * 左右padding(为了表格的美观,暂只支持统一的padding)
+ */
+ private int horizontalPadding = 40;
+
+ /**
+ * 是否显示左侧序号列
+ */
+ private boolean isShowYSequence = true;
+ /**
+ * 是否显示表格标题
+ */
+ private boolean isShowTableTitle = true;
+ /**
+ * 是否显示列标题
+ */
+ private boolean isShowColumnTitle = true;
+ /**
+ * 是否固定左侧
+ */
+ private boolean fixedYSequence = false;
+ /**
+ * 固定顶部
+ */
+ private boolean fixedXSequence = false;
+ /**
+ * 固定标题
+ */
+ private boolean fixedTitle = false;
+ /**
+ * 是否固定统计行
+ */
+ private boolean fixedCountRow = true;
+ /**
+ * 左上角空隙背景颜色
+ */
+ private int leftAndTopBackgroundColor;
+
+
+ private int minTableWidth = -1;
+ /**
+ * 画笔
+ */
+ private Paint paint;
+ /**
+ * 缩放值
+ */
+ private float zoom = 1;
+ private static TableConfig tableConfig;
+
+ public static TableConfig getInstance() {
+ if (tableConfig == null) {
+ tableConfig = new TableConfig();
+ }
+ return tableConfig;
+ }
+
+ private TableConfig() {
+
+ }
+
+ public int getVerticalPadding() {
+ return verticalPadding;
+ }
+
+ public TableConfig setVerticalPadding(int verticalPadding) {
+ this.verticalPadding = verticalPadding;
+ return this;
+ }
+
+ public int getHorizontalPadding() {
+ return horizontalPadding;
+ }
+
+ public TableConfig setHorizontalPadding(int horizontalPadding) {
+ this.horizontalPadding = horizontalPadding;
+ return this;
+ }
+
+ public Paint getPaint() {
+ return paint;
+ }
+
+ public void setPaint(Paint paint) {
+ this.paint = paint;
+ }
+
+
+ public boolean isFixedYSequence() {
+ return fixedYSequence;
+ }
+
+ public TableConfig setFixedYSequence(boolean fixedYSequence) {
+ this.fixedYSequence = fixedYSequence;
+ return this;
+ }
+
+ public boolean isFixedXSequence() {
+ return fixedXSequence;
+ }
+
+ public TableConfig setFixedXSequence(boolean fixedXSequence) {
+ this.fixedXSequence = fixedXSequence;
+ return this;
+ }
+
+ public boolean isFixedTitle() {
+ return fixedTitle;
+ }
+
+ public boolean isFixedCountRow() {
+ return fixedCountRow;
+ }
+
+ public TableConfig setFixedCountRow(boolean fixedCountRow) {
+ this.fixedCountRow = fixedCountRow;
+ return this;
+ }
+
+ public boolean isShowYSequence() {
+ return isShowYSequence;
+ }
+
+ public TableConfig setShowYSequence(boolean showYSequence) {
+ isShowYSequence = showYSequence;
+ return this;
+ }
+
+ public float getZoom() {
+ return zoom;
+ }
+
+ public void setZoom(float zoom) {
+ this.zoom = zoom;
+ }
+
+ public int getColumnTitleHorizontalPadding() {
+ return columnTitleHorizontalPadding;
+ }
+
+ public TableConfig setColumnTitleHorizontalPadding(int columnTitleHorizontalPadding) {
+ this.columnTitleHorizontalPadding = columnTitleHorizontalPadding;
+ return this;
+ }
+
+ public boolean isShowTableTitle() {
+ return isShowTableTitle;
+ }
+
+ public TableConfig setShowTableTitle(boolean showTableTitle) {
+ isShowTableTitle = showTableTitle;
+ return this;
+ }
+
+ public boolean isShowColumnTitle() {
+
+ return isShowColumnTitle;
+ }
+
+ public int getLeftAndTopBackgroundColor() {
+ return leftAndTopBackgroundColor;
+ }
+
+ public TableConfig setLeftAndTopBackgroundColor(int leftAndTopBackgroundColor) {
+ this.leftAndTopBackgroundColor = leftAndTopBackgroundColor;
+ return this;
+ }
+
+ public TableConfig setShowColumnTitle(boolean showColumnTitle) {
+ isShowColumnTitle = showColumnTitle;
+ return this;
+ }
+
+ public TableConfig setMinTableWidth(int minTableWidth) {
+ this.minTableWidth = minTableWidth;
+ return this;
+ }
+
+ public int getMinTableWidth() {
+ return minTableWidth;
+ }
+
+
+ public int getColumnTitleVerticalPadding() {
+ return columnTitleVerticalPadding;
+ }
+
+ public TableConfig setColumnTitleVerticalPadding(int columnTitleVerticalPadding) {
+ this.columnTitleVerticalPadding = columnTitleVerticalPadding;
+ return this;
+ }
+
+
+ public int getSequenceHorizontalPadding() {
+ return sequenceHorizontalPadding;
+ }
+
+ public TableConfig setSequenceHorizontalPadding(int sequenceHorizontalPadding) {
+ this.sequenceHorizontalPadding = sequenceHorizontalPadding;
+ return this;
+ }
+
+ public int getTextLeftOffset() {
+ return textLeftOffset;
+ }
+
+ public TableConfig setTextLeftOffset(int textLeftOffset) {
+ this.textLeftOffset = textLeftOffset;
+ return this;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableMeasurer.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableMeasurer.java
new file mode 100755
index 000000000..639c4497c
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableMeasurer.java
@@ -0,0 +1,254 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview;
+
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.Log;
+
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Cell;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.ColumnInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IComponent;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ITableTitle;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+
+import java.util.List;
+
+public class TableMeasurer {
+
+ private boolean isReMeasure; //是否重新计算
+
+ public TableInfo measure(TableData tableData, int width, int height) {
+ isReMeasure = true;
+ TableInfo tableInfo = tableData.getTableInfo();
+
+ width = Math.max(getTableWidth(tableData), width);
+ height = Math.max(getTableHeight(tableData), height);
+
+ tableInfo.setTableRect(new Rect(0, 0, width, height));
+ measureColumnSize(tableData);
+ return tableInfo;
+ }
+
+
+ public void measureTableTitle(TableData tableData, ITableTitle tableTitle, Rect showRect) {
+ TableInfo tableInfo = tableData.getTableInfo();
+ Rect tableRect = tableInfo.getTableRect();
+ if (isReMeasure) {
+ isReMeasure = false;
+ int size = tableTitle.getSize();
+ tableInfo.setTitleDirection(tableTitle.getDirection());
+ tableInfo.setTableTitleSize(size);
+ if (tableTitle.getDirection() == IComponent.TOP ||
+ tableTitle.getDirection() == IComponent.BOTTOM) {
+ int height = size;
+ tableRect.bottom += height;
+ reSetShowRect(showRect, tableRect);
+ } else {
+ int width = size;
+ tableRect.right += width;
+ reSetShowRect(showRect, tableRect);
+ }
+ } else {
+ reSetShowRect(showRect, tableRect);
+ }
+
+ }
+
+ /**
+ * 重新计算显示大小
+ *
+ * @param showRect
+ * @param tableRect
+ */
+ public void reSetShowRect(Rect showRect, Rect tableRect) {
+ if (showRect.bottom > tableRect.bottom) {
+ showRect.bottom = tableRect.bottom;
+ }
+ if (showRect.right > tableRect.right) {
+ showRect.right = tableRect.right;
+ }
+ }
+
+ /**
+ * 添加table高度
+ *
+ * @param tableData
+ * @return
+ */
+ public void addTableHeight(TableData tableData) {
+// TableInfo tableInfo = tableData.getTableInfo();
+// Rect tableRect = tableInfo.getTableRect();
+// int[] lineArray = tableInfo.getLineHeightArray();
+// for(int i = startPosition;i tableData) {
+ TableConfig config = TableConfig.getInstance();
+ int topHeight = 0;
+ int titleHeight = config.isShowColumnTitle() ? (tableData.getTitleDrawFormat().measureHeight(config)
+ + 2 * config.getColumnTitleVerticalPadding()) : 0;
+ TableInfo tableInfo = tableData.getTableInfo();
+ tableInfo.setTitleHeight(titleHeight);
+ tableInfo.setTopHeight(topHeight);
+ int totalContentHeight = 0;
+ for (int height : tableInfo.getLineHeightArray()) {
+ totalContentHeight += height;
+ }
+ int totalTitleHeight = titleHeight * tableInfo.getMaxLevel();
+ int totalHeight = topHeight + totalTitleHeight + totalContentHeight;
+
+ return totalHeight;
+ }
+
+ /**
+ * 计算table宽度
+ *
+ * @param tableData
+ * @param config
+ * @return
+ */
+ private int getTableWidth(TableData tableData) {
+ int totalWidth = 0;
+ TableConfig config = TableConfig.getInstance();
+ Paint paint = config.getPaint();
+ config.YSequenceStyle.fillPaint(paint);
+ int totalSize = tableData.getLineSize();
+ //计算Y轴宽度距离
+ if (config.isShowYSequence()) {
+ int yAxisWidth = (int) paint.measureText(tableData.getYSequenceFormat().format(totalSize)
+ + 2 * config.getSequenceHorizontalPadding());
+ tableData.getTableInfo().setyAxisWidth(yAxisWidth);
+ totalWidth += yAxisWidth;
+ }
+ int columnPos = 0;
+ int contentWidth = 0;
+ int[] lineHeightArray = tableData.getTableInfo().getLineHeightArray();
+ int currentPosition, size;
+ for (Column column : tableData.getChildColumns()) {
+ float columnNameWidth = tableData.getTitleDrawFormat().measureWidth(column, config) + config.getColumnTitleHorizontalPadding() * 2;
+ int columnWidth = 0;
+ size = column.getDatas().size();
+ currentPosition = 0;
+ Cell[][] rangeCells = tableData.getTableInfo().getRangeCells();
+ for (int position = 0; position < size; position++) {
+ int width = column.getDrawFormat().measureWidth(column, position);
+ measureRowHeight(lineHeightArray, column, currentPosition, position);
+ currentPosition += 1;
+ /**
+ *Todo 为了解决合并单元宽度过大问题
+ */
+ if (rangeCells != null) {
+ Cell cell = rangeCells[position][columnPos];
+ if (cell != null) {
+ if (cell.row != Cell.INVALID && cell.col != Cell.INVALID) {
+ cell.width = width;
+ width = width / cell.col;
+ } else if (cell.realCell != null) {
+ width = cell.realCell.width / cell.realCell.col;
+ }
+
+ }
+ }
+ if (columnWidth < width) {
+ columnWidth = width;
+ }
+ }
+ int width = (int) (Math.max(columnNameWidth, columnWidth + 2 * config.getHorizontalPadding()));
+ width = Math.max(column.getMinWidth(), width);
+ column.setComputeWidth(width);
+ contentWidth += width;
+ columnPos++;
+ }
+ int minWidth = config.getMinTableWidth();
+ //计算出来的宽度大于最小宽度
+ if (minWidth == -1 || minWidth - totalWidth < contentWidth) {
+ totalWidth += contentWidth;
+ } else {
+ minWidth -= totalWidth;
+ float widthScale = ((float) minWidth) / contentWidth;
+ for (Column column : tableData.getChildColumns()) {
+ column.setComputeWidth((int) (widthScale * column.getComputeWidth()));
+ }
+ totalWidth += minWidth;
+ }
+ return totalWidth;
+ }
+
+
+ /**
+ * 测量行高
+ *
+ * @param config
+ * @param lineHeightArray
+ * @param column
+ * @param position
+ */
+ private void measureRowHeight(int[] lineHeightArray, Column column, int currentPosition, int position) {
+ TableConfig config = TableConfig.getInstance();
+
+ int height = 0;
+ if (height == 0) {
+ height = column.getDrawFormat().measureHeight(column, position) +
+ 2 * config.getVerticalPadding();
+ }
+ height = Math.max(column.getMinHeight(), height);
+ if (height > lineHeightArray[currentPosition]) {
+ lineHeightArray[currentPosition] = height;
+ }
+ }
+
+ /**
+ * 测量列的Rect
+ *
+ * @param tableData
+ */
+ private void measureColumnSize(TableData tableData) {
+ List columnList = tableData.getColumns();
+ int left = 0;
+ int maxLevel = tableData.getTableInfo().getMaxLevel();
+ tableData.getColumnInfos().clear();
+ tableData.getChildColumnInfos().clear();
+ for (int i = 0; i < columnList.size(); i++) {
+ int top = 0;
+ Column column = columnList.get(i);
+ ColumnInfo columnInfo = getColumnInfo(tableData, column, null, left, top, maxLevel);
+ left += columnInfo.width;
+ }
+ }
+
+ public ColumnInfo getColumnInfo(TableData tableData, Column column, ColumnInfo parent, int left, int top, int overLevel) {
+ TableInfo tableInfo = tableData.getTableInfo();
+ ColumnInfo columnInfo = new ColumnInfo();
+ columnInfo.value = column.getColumnName();
+ columnInfo.column = column;
+ columnInfo.width = column.getComputeWidth();
+ columnInfo.top = top;
+ columnInfo.height = tableInfo.getTitleHeight() * overLevel;
+ columnInfo.left = left;
+
+ tableData.getChildColumnInfos().add(columnInfo);
+ tableData.getColumnInfos().add(columnInfo);
+
+
+ return columnInfo;
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableParser.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableParser.java
new file mode 100755
index 000000000..20c83ffa9
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableParser.java
@@ -0,0 +1,72 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.ArrayTableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableInfo;
+
+import java.util.List;
+
+public class TableParser {
+
+ /**
+ * 解析数据
+ */
+ public List parse(TableData tableData) {
+
+ tableData.getChildColumns().clear();
+ tableData.getColumnInfos().clear();
+ int maxLevel = getChildColumn(tableData);
+ TableInfo tableInfo = tableData.getTableInfo();
+ tableInfo.setColumnSize(tableData.getChildColumns().size());
+ tableInfo.setMaxLevel(maxLevel);
+ if (!(tableData instanceof ArrayTableData)) {
+ for (Column column : tableData.getChildColumns()) {
+ column.getDatas().clear();
+ }
+ }
+ return tableData.getColumns();
+ }
+
+ /**
+ * 添加数据
+ */
+ public void addData(TableData tableData, List addData, boolean isFoot) {
+ if (isFoot) {
+ tableData.getT().addAll(addData);
+ } else {
+ tableData.getT().addAll(0, addData);
+ }
+ TableInfo tableInfo = tableData.getTableInfo();
+ tableInfo.addLine(addData.size(), isFoot);
+
+
+ }
+
+ private int getChildColumn(TableData tableData) {
+ int maxLevel = 0;
+ for (Column column : tableData.getColumns()) {
+ int level = getColumnLevel(tableData, column, 0);
+ if (level > maxLevel) {
+ maxLevel = level;
+ }
+ }
+ return maxLevel;
+ }
+
+ /**
+ * 得到列的层级
+ *
+ * @param tableData 表格数据
+ * @param column 列
+ * @param level 层级
+ * @return
+ */
+ private int getColumnLevel(TableData tableData, Column column, int level) {
+ level++;
+ tableData.getChildColumns().add(column);
+ return level;
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableProvider.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableProvider.java
new file mode 100755
index 000000000..a96115ca9
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/TableProvider.java
@@ -0,0 +1,460 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview;
+
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Cell;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.CellInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.ColumnInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ISelectFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.listener.OnColumnClickListener;
+import com.didichuxing.doraemonkit.ui.widget.tableview.listener.TableClickObserver;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+
+import java.util.List;
+public class TableProvider implements TableClickObserver {
+
+
+ private Rect scaleRect;
+ private Rect showRect;
+ private TableConfig config;
+ private PointF clickPoint;
+ private ColumnInfo clickColumnInfo;
+ private boolean isClickPoint;
+ private OnColumnClickListener onColumnClickListener;
+ /**
+ * 选中格子格式化
+ */
+ private SelectionOperation operation;
+ private TableData tableData;
+ private Rect clipRect;
+ private Rect tempRect; //用于存储数据
+ private PointF tipPoint = new PointF();
+ private CellInfo cellInfo = new CellInfo();
+
+ public TableProvider() {
+
+ clickPoint = new PointF(-1, -1);
+ clipRect = new Rect();
+ tempRect = new Rect();
+ operation = new SelectionOperation();
+ config = TableConfig.getInstance();
+ }
+
+ /**
+ * 绘制
+ *
+ * @param canvas 画布
+ * @param scaleRect 缩放Rect
+ * @param showRect 显示Rect
+ * @param tableData 表格数据
+ * @param config 配置
+ */
+ public void onDraw(Canvas canvas, Rect scaleRect, Rect showRect,
+ TableData tableData) {
+ setData(scaleRect, showRect, tableData);
+ canvas.save();
+ canvas.clipRect(this.showRect);
+ drawColumnTitle(canvas);
+ drawCount(canvas);
+ drawContent(canvas);
+ operation.draw(canvas, showRect, config);
+ canvas.restore();
+ if (isClickPoint && clickColumnInfo != null) {
+ onColumnClickListener.onClick(clickColumnInfo);
+ }
+ }
+
+ /**
+ * 设置基本信息和清除数据
+ *
+ * @param scaleRect 缩放Rect
+ * @param showRect 显示Rect
+ * @param tableData 表格数据
+ */
+ private void setData(Rect scaleRect, Rect showRect, TableData tableData) {
+ isClickPoint = false;
+ clickColumnInfo = null;
+ operation.reset();
+ this.scaleRect = scaleRect;
+ this.showRect = showRect;
+ this.tableData = tableData;
+ }
+
+
+ private void drawColumnTitle(Canvas canvas) {
+ if (config.isShowColumnTitle()) {
+ if (config.isFixedTitle()) {
+ drawTitle(canvas);
+ canvas.restore();
+ canvas.save();
+ canvas.clipRect(this.showRect);
+ } else {
+ drawTitle(canvas);
+ }
+ }
+ }
+
+ /**
+ * 绘制统计行
+ *
+ * @param canvas 画布
+ */
+ private void drawCount(Canvas canvas) {
+
+ float left = scaleRect.left;
+ float bottom = config.isFixedCountRow() ? Math.min(scaleRect.bottom, showRect.bottom) : scaleRect.bottom;
+ int countHeight = tableData.getTableInfo().getCountHeight();
+ float top = bottom - countHeight;
+ List childColumnInfos = tableData.getChildColumnInfos();
+ if (DrawUtils.isVerticalMixRect(showRect, (int) top, (int) bottom)) {
+ List columns = tableData.getChildColumns();
+ int columnSize = columns.size();
+ boolean isPerColumnFixed = false;
+ clipRect.set(showRect);
+ int clipCount = 0;
+ for (int i = 0; i < columnSize; i++) {
+ Column column = columns.get(i);
+ float tempLeft = left;
+ float width = column.getComputeWidth() * config.getZoom();
+ if (childColumnInfos.get(i).column.isFixed()) {
+ if (left < clipRect.left) {
+ left = clipRect.left;
+ clipRect.left += width;
+ isPerColumnFixed = true;
+ }
+ } else if (isPerColumnFixed) {
+ canvas.save();
+ clipCount++;
+ canvas.clipRect(clipRect.left, showRect.bottom - countHeight,
+ showRect.right, showRect.bottom);
+ }
+ tempRect.set((int) left, (int) top, (int) (left + width), (int) bottom);
+ left = tempLeft;
+ left += width;
+ }
+ for (int i = 0; i < clipCount; i++) {
+ canvas.restore();
+ }
+ }
+ }
+
+ /**
+ * 绘制列标题
+ *
+ * @param canvas 画布
+ */
+ private void drawTitle(Canvas canvas) {
+ int dis = showRect.top - scaleRect.top;
+ TableInfo tableInfo = tableData.getTableInfo();
+ int titleHeight = tableInfo.getTitleHeight() * tableInfo.getMaxLevel();
+ int clipHeight = config.isFixedTitle() ? titleHeight : Math.max(0, titleHeight - dis);
+
+ clipRect.set(showRect);
+ List columnInfoList = tableData.getColumnInfos();
+ float zoom = config.getZoom();
+ boolean isPerColumnFixed = false;
+ int clipCount = 0;
+ ColumnInfo parentColumnInfo = null;
+ for (ColumnInfo info : columnInfoList) {
+ int left = (int) (info.left * zoom + scaleRect.left);
+ //根据top ==0是根部,根据最根部的Title判断是否需要固定
+ if (info.top == 0 && info.column.isFixed()) {
+ if (left < clipRect.left) {
+ parentColumnInfo = info;
+ left = clipRect.left;
+ fillColumnTitle(canvas, info, left);
+ clipRect.left += info.width * zoom;
+ isPerColumnFixed = true;
+ continue;
+ }
+ //根部需要固定,同时固定所有子类
+ } else if (isPerColumnFixed && info.top != 0) {
+ left = (int) (clipRect.left - info.width * zoom);
+ left += (info.left - parentColumnInfo.left);
+ } else if (isPerColumnFixed) {
+ canvas.save();
+ canvas.clipRect(clipRect.left, showRect.top, showRect.right,
+ showRect.top + clipHeight);
+ isPerColumnFixed = false;
+ clipCount++;
+ }
+ fillColumnTitle(canvas, info, left);
+ }
+ for (int i = 0; i < clipCount; i++) {
+ canvas.restore();
+ }
+ if (config.isFixedTitle()) {
+ scaleRect.top += titleHeight;
+ showRect.top += titleHeight;
+ } else {
+ showRect.top += clipHeight;
+ scaleRect.top += titleHeight;
+ }
+
+ }
+
+ /**
+ * 填充列标题
+ *
+ * @param canvas 画布
+ * @param info 列信息
+ * @param left 左边
+ */
+ private void fillColumnTitle(Canvas canvas, ColumnInfo info, int left) {
+
+ int top = (int) (info.top * config.getZoom())
+ + (config.isFixedTitle() ? showRect.top : scaleRect.top);
+ int right = (int) (left + info.width * config.getZoom());
+ int bottom = (int) (top + info.height * config.getZoom());
+ if (DrawUtils.isMixRect(showRect, left, top, right, bottom)) {
+ if (!isClickPoint && onColumnClickListener != null) {
+ if (DrawUtils.isClick(left, top, right, bottom, clickPoint)) {
+ isClickPoint = true;
+ clickColumnInfo = info;
+ clickPoint.set(-1, -1);
+ }
+ }
+
+ Paint paint = config.getPaint();
+ tempRect.set(left, top, right, bottom);
+ config.columnTitleGridStyle.fillPaint(paint);
+ canvas.drawRect(tempRect, paint);
+
+ tableData.getTitleDrawFormat().draw(canvas, info.column, tempRect, config);
+
+ }
+ }
+
+ /**
+ * 绘制内容
+ *
+ * @param canvas 画布
+ */
+ private void drawContent(Canvas canvas) {
+ float top;
+ float left = scaleRect.left;
+ List columns = tableData.getChildColumns();
+ clipRect.set(showRect);
+ TableInfo info = tableData.getTableInfo();
+ int columnSize = columns.size();
+
+ if (config.isFixedCountRow()) {
+ canvas.save();
+ canvas.clipRect(showRect.left, showRect.top, showRect.right, showRect.bottom - info.getCountHeight());
+ }
+ List childColumnInfo = tableData.getChildColumnInfos();
+ boolean isPerFixed = false;
+ int clipCount = 0;
+ Rect correctCellRect;
+ for (int i = 0; i < columnSize; i++) {
+ top = scaleRect.top;
+ Column column = columns.get(i);
+ float width = column.getComputeWidth() * config.getZoom();
+ float tempLeft = left;
+ //根据根部标题是否固定
+ Column topColumn = childColumnInfo.get(i).column;
+ if (topColumn.isFixed()) {
+ isPerFixed = false;
+ if (tempLeft < clipRect.left) {
+ left = clipRect.left;
+ clipRect.left += width;
+ isPerFixed = true;
+ }
+ } else if (isPerFixed) {
+ canvas.save();
+ canvas.clipRect(clipRect);
+ isPerFixed = false;
+ clipCount++;
+ }
+ float right = left + width;
+
+ if (left < showRect.right) {
+ int size = column.getDatas().size();
+ int realPosition = 0;
+ for (int j = 0; j < size; j++) {
+ String value = column.format(j);
+ int totalLineHeight = 0;
+ for (int k = realPosition; k < realPosition + 1; k++) {
+ totalLineHeight += info.getLineHeightArray()[k];
+ }
+ realPosition += 1;
+ float bottom = top + totalLineHeight * config.getZoom();
+ tempRect.set((int) left, (int) top, (int) right, (int) bottom);
+ correctCellRect = correctCellRect(j, i, tempRect, config.getZoom()); //矫正格子的大小
+ if (correctCellRect != null) {
+ if (correctCellRect.top < showRect.bottom) {
+ if (correctCellRect.right > showRect.left && correctCellRect.bottom > showRect.top) {
+ Object data = column.getDatas().get(j);
+ if (DrawUtils.isClick(correctCellRect, clickPoint)) {
+ operation.setSelectionRect(i, j, correctCellRect);
+ tipPoint.x = (left + right) / 2;
+ tipPoint.y = (top + bottom) / 2;
+ clickColumn(column, j, value, data);
+ isClickPoint = true;
+ clickPoint.set(-Integer.MAX_VALUE, -Integer.MAX_VALUE);
+ }
+ operation.checkSelectedPoint(i, j, correctCellRect);
+ cellInfo.set(column, data, value, i, j);
+ drawContentCell(canvas, cellInfo, correctCellRect);
+
+ }
+ } else {
+ break;
+ }
+ }
+ top = bottom;
+ }
+ left = tempLeft + width;
+ } else {
+ break;
+ }
+ }
+ for (int i = 0; i < clipCount; i++) {
+ canvas.restore();
+ }
+ if (config.isFixedCountRow()) {
+ canvas.restore();
+ }
+ }
+
+ /**
+ * 绘制内容格子
+ *
+ * @param c 画布
+ * @param cellInfo 格子信息
+ * @param rect 方位
+ * @param config 表格配置
+ */
+ protected void drawContentCell(Canvas c, CellInfo cellInfo, Rect rect) {
+
+ config.contentGridStyle.fillPaint(config.getPaint());
+ c.drawRect(rect, config.getPaint());
+
+ rect.left += config.getTextLeftOffset();
+ cellInfo.column.getDrawFormat().draw(c, rect, cellInfo);
+ }
+
+ /**
+ * 点击格子
+ *
+ * @param column 列
+ * @param position 位置
+ * @param value 值
+ * @param data 数据
+ */
+ private void clickColumn(Column column, int position, String value, Object data) {
+ if (!isClickPoint && column.getOnColumnItemClickListener() != null) {
+ column.getOnColumnItemClickListener().onClick(column, value, data, position);
+ }
+ }
+
+ @Override
+ public void onClick(float x, float y) {
+ clickPoint.x = x;
+ clickPoint.y = y;
+ }
+
+ public OnColumnClickListener getOnColumnClickListener() {
+ return onColumnClickListener;
+ }
+
+ public void setOnColumnClickListener(OnColumnClickListener onColumnClickListener) {
+ this.onColumnClickListener = onColumnClickListener;
+ }
+
+ public void setSelectFormat(ISelectFormat selectFormat) {
+ this.operation.setSelectFormat(selectFormat);
+ }
+
+ /**
+ * 计算任何point在View的位置
+ *
+ * @param row 列
+ * @param col 行
+ * @return
+ */
+ public int[] getPointLocation(double row, double col) {
+ List childColumns = tableData.getChildColumns();
+ int[] lineHeights = tableData.getTableInfo().getLineHeightArray();
+ int x = 0, y = 0;
+ int columnSize = childColumns.size();
+ for (int i = 0; i <= (columnSize > col + 1 ? col + 1 : columnSize - 1); i++) {
+ int w = childColumns.get(i).getComputeWidth();
+ if (i == (int) col + 1) {
+ x += w * (col - (int) col);
+ } else {
+ x += w;
+ }
+ }
+ for (int i = 0; i <= (lineHeights.length > row + 1 ? row + 1 : lineHeights.length - 1); i++) {
+ int h = lineHeights[i];
+ if (i == (int) row + 1) {
+ y += h * (row - (int) row);
+ } else {
+ y += h;
+ }
+ }
+ x *= config.getZoom();
+ y *= config.getZoom();
+ x += scaleRect.left;
+ y += scaleRect.top;
+ return new int[]{x, y};
+
+ }
+
+ /**
+ * 计算任何point在View的大小
+ *
+ * @param row 列
+ * @param col 行
+ * @return
+ */
+ public int[] getPointSize(int row, int col) {
+ List childColumns = tableData.getChildColumns();
+ int[] lineHeights = tableData.getTableInfo().getLineHeightArray();
+ col = col < childColumns.size() ? col : childColumns.size() - 1;//列
+ row = row < lineHeights.length ? row : lineHeights.length;//行
+ col = col < 0 ? 0 : col;
+ row = row < 0 ? 0 : row;
+ return new int[]{(int) (childColumns.get(col).getComputeWidth() * config.getZoom()),
+ (int) (lineHeights[row] * config.getZoom())};
+
+ }
+
+ private Rect correctCellRect(int row, int col, Rect rect, float zoom) {
+ Cell[][] rangePoints = tableData.getTableInfo().getRangeCells();
+ if (rangePoints != null && rangePoints.length > row) {
+ Cell point = rangePoints[row][col];
+ if (point != null) {
+ if (point.col != Cell.INVALID && point.row != Cell.INVALID) {
+ List childColumns = tableData.getChildColumns();
+ int[] lineHeights = tableData.getTableInfo().getLineHeightArray();
+ int width = 0, height = 0;
+ for (int i = col; i < Math.min(childColumns.size(), col + point.col); i++) {
+ width += childColumns.get(i).getComputeWidth();
+ }
+ for (int i = row; i < Math.min(lineHeights.length, row + point.row); i++) {
+ height += lineHeights[i];
+ }
+ rect.right = (int) (rect.left + width * zoom);
+ rect.bottom = (int) (rect.top + height * zoom);
+ return rect;
+ }
+ return null;
+ }
+ }
+ return rect;
+ }
+
+ public SelectionOperation getOperation() {
+ return operation;
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/ArrayTableData.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/ArrayTableData.java
new file mode 100755
index 000000000..41a72bc17
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/ArrayTableData.java
@@ -0,0 +1,139 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.component.SmartTable;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IDrawFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IFormat;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ArrayTableData extends TableData {
+
+ private T[][] data;
+ private List> arrayColumns;
+
+ /**
+ * 创建二维数组表格数据
+ * 如果数据不是数组[row][col],可以使用transformColumnArray方法转换
+ *
+ * @param tableName 表名
+ * @param titleNames 列名
+ * @param data 数据 数组[row][col]
+ * @param drawFormat 数据格式化
+ * @return 创建的二维数组表格数据
+ */
+ public static ArrayTableData create(String tableName, String[] titleNames, T[][] data, IDrawFormat drawFormat) {
+ List> columns = new ArrayList<>();
+ for (int i = 0; i < data.length; i++) {
+ T[] dataArray = data[i];
+ Column column = new Column<>(titleNames == null ? "" : titleNames[i], null, drawFormat);
+ column.setDatas(Arrays.asList(dataArray));
+ columns.add(column);
+ }
+ ArrayList arrayList = new ArrayList<>(Arrays.asList(data[0]));
+ ArrayTableData tableData = new ArrayTableData<>(tableName, arrayList, columns);
+ tableData.setData(data);
+ return tableData;
+ }
+
+ /**
+ * 创建不需要显示列名的二维数组表格数据
+ * 如果数据不是数组[row][col],可以使用transformColumnArray方法转换
+ *
+ * @param tableName 表名
+ * @param data 数据 数组[row][col]
+ * @param drawFormat 数据格式化
+ * @return 创建的二维数组表格数据
+ */
+ public static ArrayTableData create(String tableName, T[][] data, IDrawFormat drawFormat) {
+ TableConfig.getInstance().setShowColumnTitle(false);
+ return create(tableName, null, data, drawFormat);
+ }
+
+ /**
+ * 设置默认格式化
+ *
+ * @param format
+ */
+ public void setFormat(IFormat format) {
+ for (Column column : arrayColumns) {
+ column.setFormat(format);
+ }
+ }
+
+ /**
+ * 设置绘制格式化
+ *
+ * @param format
+ */
+ public void setDrawFormat(IDrawFormat format) {
+ for (Column column : arrayColumns) {
+ column.setDrawFormat(format);
+ }
+ }
+
+ /**
+ * 设置最小宽度
+ *
+ * @param minWidth
+ */
+ public void setMinWidth(int minWidth) {
+ for (Column column : arrayColumns) {
+ column.setMinWidth(minWidth);
+ }
+ }
+
+ /**
+ * 设置最小高度
+ *
+ * @param minHeight
+ */
+ public void setMinHeight(int minHeight) {
+ for (Column column : arrayColumns) {
+ column.setMinHeight(minHeight);
+ }
+ }
+
+
+ /**
+ * 二维数组的构造方法
+ *
+ * @param tableName 表名
+ * @param t 数据
+ * @param columns 列
+ */
+ protected ArrayTableData(String tableName, List t, List> columns) {
+ super(tableName, t, new ArrayList(columns));
+ this.arrayColumns = columns;
+ }
+
+ /**
+ * 获取当前的列
+ */
+ public List> getArrayColumns() {
+ return arrayColumns;
+ }
+
+
+ /**
+ * 获取二维数组数据
+ */
+ public T[][] getData() {
+ return data;
+ }
+
+ /**
+ * 设置二维数组数据
+ *
+ * @param data
+ */
+ public void setData(T[][] data) {
+ this.data = data;
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/Cell.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/Cell.java
new file mode 100644
index 000000000..3b8e9849d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/Cell.java
@@ -0,0 +1,12 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+public class Cell {
+ public static final int INVALID = -1;
+
+ public int col;
+ public int row;
+ public Cell realCell;
+ public int width;
+ public int height;
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/CellInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/CellInfo.java
new file mode 100755
index 000000000..db2255624
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/CellInfo.java
@@ -0,0 +1,34 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+public class CellInfo {
+ /**
+ * 数据
+ */
+ public T data;
+ /**
+ * 所在行位置
+ */
+ public int row;
+ /**
+ * 所在列位置
+ */
+ public int col;
+
+ /**
+ * 所在列
+ */
+ public Column column;
+ /**
+ * 显示的值
+ */
+ public String value;
+
+ public void set(Column column, T t, String value, int col, int row) {
+ this.column = column;
+ this.value = value;
+ this.data = t;
+ this.row = row;
+ this.col = col;
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/Column.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/Column.java
new file mode 100755
index 000000000..b76bbb47b
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/Column.java
@@ -0,0 +1,284 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+import android.graphics.Paint;
+import android.util.Log;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.format.FastTextDrawFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IDrawFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.listener.OnColumnItemClickListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class Column implements Comparable {
+
+ public static final String INVAL_VALUE = "";
+ /**
+ * 列名
+ */
+ private String columnName;
+
+ private IFormat format;
+ private IDrawFormat drawFormat = new FastTextDrawFormat();
+ private List datas;
+ private boolean isFixed;
+ private int computeWidth;
+ private OnColumnItemClickListener onColumnItemClickListener;
+ private Paint.Align textAlign;
+ private Paint.Align titleAlign;
+ private int id;
+ private int minWidth;
+ private int minHeight;
+ private int width;
+
+
+ /**
+ * 列构造方法
+ * 用于构造子列
+ *
+ * @param columnName 列名
+ * @param fieldName 需要解析的反射字段
+ * @param format 文字格式化
+ * @param drawFormat 绘制格式化
+ */
+ public Column(String columnName, IFormat format, IDrawFormat drawFormat) {
+ this.columnName = columnName;
+ this.format = format;
+ if (drawFormat != null) {
+ this.drawFormat = drawFormat;
+ }
+ datas = new ArrayList<>();
+ }
+
+
+ /**
+ * 获取列名
+ *
+ * @return 列名
+ */
+ public String getColumnName() {
+ return columnName;
+ }
+
+ /**
+ * 设置列名
+ *
+ * @param columnName 列名
+ */
+ public void setColumnName(String columnName) {
+ this.columnName = columnName;
+ }
+
+ /**
+ * 获取文字格式化
+ *
+ * @return 文字格式化
+ */
+ public IFormat getFormat() {
+ return format;
+ }
+
+ /**
+ * 设置文字格式化
+ */
+ public void setFormat(IFormat format) {
+ this.format = format;
+ }
+
+ /**
+ * 获取绘制格式化
+ *
+ * @return 绘制格式化
+ */
+ public IDrawFormat getDrawFormat() {
+ return drawFormat;
+ }
+
+ /**
+ * 设置绘制格式化
+ */
+ public void setDrawFormat(IDrawFormat drawFormat) {
+ this.drawFormat = drawFormat;
+ }
+
+ /**
+ * 获取需要解析的数据
+ *
+ * @return 数据
+ */
+ public List getDatas() {
+ return datas;
+ }
+
+ /**
+ * 设置需要解析的数据
+ * 直接设置数据,不需要反射获取值
+ */
+ public void setDatas(List datas) {
+ this.datas = datas;
+ }
+
+
+ public String format(int position) {
+ if (position >= 0 && position < datas.size()) {
+ return format(datas.get(position));
+ }
+ return INVAL_VALUE;
+ }
+
+ public String format(T t) {
+ String value;
+ if (format != null) {
+ value = format.format(t);
+ } else {
+ value = t == null ? INVAL_VALUE : t.toString();
+ }
+ return value;
+ }
+
+ /**
+ * 获取列的计算的宽度
+ *
+ * @return 宽度
+ */
+ public int getComputeWidth() {
+ return computeWidth;
+ }
+
+ /**
+ * 设置列的计算宽度
+ */
+ public void setComputeWidth(int computeWidth) {
+ this.computeWidth = computeWidth;
+ }
+
+ /**
+ * 获取列ID
+ *
+ * @return ID
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * 设置列ID
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * 比较
+ */
+ @Override
+ public int compareTo(Column o) {
+ return this.id - o.getId();
+ }
+
+
+ /**
+ * 获取点击列监听
+ *
+ * @return 点击列监听
+ */
+ public OnColumnItemClickListener getOnColumnItemClickListener() {
+ return onColumnItemClickListener;
+ }
+
+ /**
+ * 设置点击列监听
+ */
+ public void setOnColumnItemClickListener(OnColumnItemClickListener onColumnItemClickListener) {
+ this.onColumnItemClickListener = onColumnItemClickListener;
+ }
+
+
+ /**
+ * 判断是否固定
+ *
+ * @return 是否固定
+ */
+ public boolean isFixed() {
+ return isFixed;
+ }
+
+ /**
+ * 设置是否固定
+ */
+ public void setFixed(boolean fixed) {
+ isFixed = fixed;
+ }
+
+ /**
+ * 获取字体位置
+ *
+ * @return Align
+ */
+ public Paint.Align getTextAlign() {
+ return textAlign;
+ }
+
+ /**
+ * 设置字体位置
+ */
+ public void setTextAlign(Paint.Align textAlign) {
+ this.textAlign = textAlign;
+ }
+
+ public int getMinWidth() {
+ return minWidth;
+ }
+
+ public void setMinWidth(int minWidth) {
+ this.minWidth = minWidth;
+ }
+
+ public int getMinHeight() {
+ return minHeight;
+ }
+
+ public void setMinHeight(int minHeight) {
+ this.minHeight = minHeight;
+ }
+
+
+ public Paint.Align getTitleAlign() {
+ return titleAlign;
+ }
+
+ /**
+ * 设置标题对齐方式
+ *
+ * @param titleAlign
+ */
+ public void setTitleAlign(Paint.Align titleAlign) {
+ this.titleAlign = titleAlign;
+ }
+
+ /**
+ * 设置列的宽度
+ *
+ * @param width
+ */
+ public void setWidth(int width) {
+ if (width > 0) {
+ this.width = width;
+ this.setDrawFormat(new FastTextDrawFormat());
+ }
+ }
+
+ /**
+ * 获取列的宽度
+ *
+ * @param
+ */
+ public int getWidth() {
+ if (width == 0) {
+ return computeWidth;
+ }
+ return width;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/ColumnInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/ColumnInfo.java
new file mode 100755
index 000000000..784986c9e
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/ColumnInfo.java
@@ -0,0 +1,31 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+
+
+public class ColumnInfo {
+ /**
+ * 列宽度
+ */
+ public int width;
+ /**
+ * 列高度
+ */
+ public int height;
+ /**
+ * 列左边
+ */
+ public int left;
+ /**
+ * 列顶部
+ */
+ public int top;
+ /**
+ * 值
+ */
+ public String value;
+ /**
+ * 列
+ */
+ public Column column;
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/TableData.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/TableData.java
new file mode 100755
index 000000000..8d658389b
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/TableData.java
@@ -0,0 +1,379 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.format.NumberSequenceFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.format.TitleDrawFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ISequenceFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ITitleDrawFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.listener.OnColumnItemClickListener;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+public class TableData {
+
+ private String tableName;
+ private List columns;
+ private List t;
+ private List childColumns;
+ private TableInfo tableInfo = new TableInfo();
+ private List columnInfos;
+ private List childColumnInfos;
+ private Column sortColumn;
+ private ITitleDrawFormat titleDrawFormat;
+ private ISequenceFormat YSequenceFormat;
+
+ private OnItemClickListener onItemClickListener;
+ private OnRowClickListener onRowClickListener;
+ private OnColumnClickListener> onColumnClickListener;
+
+ /**
+ * @param tableName 表名
+ * @param t 数据
+ * @param columns 列列表
+ */
+ public TableData(String tableName, List t, List columns) {
+ this(tableName, t, columns, null);
+
+ }
+
+ /**
+ * @param tableName 表名
+ * @param t 数据
+ * @param columns 列列表
+ */
+ public TableData(String tableName, List t, Column... columns) {
+ this(tableName, t, Arrays.asList(columns));
+ }
+
+ /**
+ * @param tableName 表名
+ * @param t 数据
+ * @param columns 列列表
+ * @param titleDrawFormat 列标题绘制格式化
+ */
+ public TableData(String tableName, List t, List columns, ITitleDrawFormat titleDrawFormat) {
+ this.tableName = tableName;
+ this.columns = columns;
+ this.t = t;
+ tableInfo.setLineSize(t.size());
+ childColumns = new ArrayList<>();
+ columnInfos = new ArrayList<>();
+ childColumnInfos = new ArrayList<>();
+ this.titleDrawFormat = titleDrawFormat == null ? new TitleDrawFormat() : titleDrawFormat;
+ }
+
+
+ /**
+ * 获取表名
+ *
+ * @return 表名
+ */
+ public String getTableName() {
+ return tableName;
+ }
+
+ /**
+ * 设置表名
+ */
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ /**
+ * 获取所有列
+ *
+ * @return 所有列
+ */
+ public List getColumns() {
+ return columns;
+ }
+
+ /**
+ * 设置新列列表
+ */
+ public void setColumns(List columns) {
+ this.columns = columns;
+ }
+
+ /**
+ * 获取解析数据
+ *
+ * @return 解析数据
+ */
+ public List getT() {
+ return t;
+ }
+
+ /**
+ * 设置解析数据
+ */
+ public void setT(List t) {
+ this.t = t;
+ tableInfo.setLineSize(t.size());
+ }
+
+
+ /**
+ * 获取所有需要显示列数据的列
+ * isParent true的列不包含
+ *
+ * @return 所有需要显示列数据的列
+ */
+ public List getChildColumns() {
+ return childColumns;
+ }
+
+ /**
+ * 获取表格信息
+ *
+ * @return 表格信息tableInfo
+ */
+ public TableInfo getTableInfo() {
+ return tableInfo;
+ }
+
+ /**
+ * 设置表格信息
+ * 一般情况下不会使用到这个方法
+ */
+ public void setTableInfo(TableInfo tableInfo) {
+ this.tableInfo = tableInfo;
+ }
+
+ /**
+ * 获取列信息列表
+ *
+ * @return 列信息列表
+ */
+ public List getColumnInfos() {
+ return columnInfos;
+ }
+
+ /**
+ * 获取isParent false列(子列)信息列表
+ *
+ * @return 子列信息列表
+ */
+ public List getChildColumnInfos() {
+ return childColumnInfos;
+ }
+
+ /**
+ * 设置子列信息列表
+ */
+ public void setChildColumnInfos(List childColumnInfos) {
+ this.childColumnInfos = childColumnInfos;
+ }
+
+ /**
+ * 设置列信息列表
+ */
+ public void setColumnInfos(List columnInfos) {
+ this.columnInfos = columnInfos;
+ }
+
+ /**
+ * 设置子列
+ */
+ public void setChildColumns(List childColumns) {
+ this.childColumns = childColumns;
+ }
+
+ /**
+ * 获取需要根据排序的列
+ *
+ * @return 排序的列
+ */
+ public Column getSortColumn() {
+ return sortColumn;
+ }
+
+ /**
+ * 设置需要根据排序的列
+ */
+ public void setSortColumn(Column sortColumn) {
+ this.sortColumn = sortColumn;
+ }
+
+
+ /**
+ * 获取列标题绘制格式化
+ *
+ * @return 列标题绘制格式化
+ */
+ public ITitleDrawFormat getTitleDrawFormat() {
+ return titleDrawFormat;
+ }
+
+ /**
+ * 设置列标题绘制格式化
+ * 通过这个方法可以对列名进行格式化
+ */
+ public void setTitleDrawFormat(ITitleDrawFormat titleDrawFormat) {
+ this.titleDrawFormat = titleDrawFormat;
+ }
+
+ /**
+ * 获取Y序号列文字格式化
+ *
+ * @return Y序号列文字格式化
+ */
+ public ISequenceFormat getYSequenceFormat() {
+ if (YSequenceFormat == null) {
+ YSequenceFormat = new NumberSequenceFormat();
+ }
+ return YSequenceFormat;
+ }
+
+ /**
+ * 设置Y序号列文字格式化
+ */
+ public void setYSequenceFormat(ISequenceFormat YSequenceFormat) {
+ this.YSequenceFormat = YSequenceFormat;
+ }
+
+ /**
+ * 获取包含ID的子列
+ *
+ * @param id 列ID
+ * @return 包含ID的子列
+ */
+ public Column getColumnByID(int id) {
+ List columns = getChildColumns();
+ for (Column column : columns) {
+ if (column.getId() == id) {
+ return column;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * 获取行数
+ *
+ * @return 行数
+ */
+ public int getLineSize() {
+ return tableInfo.getLineHeightArray().length;
+ }
+
+ public void clear() {
+ if (t != null) {
+ t.clear();
+ t = null;
+ }
+ if (childColumns != null) {
+ childColumns.clear();
+ childColumns = null;
+ }
+ if (columns != null) {
+ columns = null;
+ }
+ if (childColumnInfos != null) {
+ childColumnInfos.clear();
+ childColumnInfos = null;
+ }
+ /* if(cellRangeAddresses !=null){
+ cellRangeAddresses.clear();
+ cellRangeAddresses =null;
+ }*/
+
+ if (tableInfo != null) {
+ tableInfo.clear();
+ tableInfo = null;
+ }
+ sortColumn = null;
+ titleDrawFormat = null;
+ YSequenceFormat = null;
+
+ }
+
+ /**
+ * 获取表格单元格Cell点击事件
+ */
+ public OnItemClickListener getOnItemClickListener() {
+ return onItemClickListener;
+
+ }
+
+ /**
+ * 设置表格单元格Cell点击事件
+ *
+ * @param onItemClickListener 点击事件
+ */
+ public void setOnItemClickListener(final OnItemClickListener onItemClickListener) {
+ this.onItemClickListener = onItemClickListener;
+ for (Column column : columns) {
+ column.setOnColumnItemClickListener(new OnColumnItemClickListener() {
+ @Override
+ public void onClick(Column column, String value, Object t, int position) {
+ if (onItemClickListener != null) {
+ int index = childColumns.indexOf(column);
+ TableData.this.onItemClickListener.onClick(column, value, t, index, position);
+ }
+ }
+ });
+ }
+ }
+
+
+ /**
+ * 设置表格行点击事件
+ *
+ * @param onRowClickListener 行点击事件
+ */
+ public void setOnRowClickListener(final OnRowClickListener onRowClickListener) {
+ this.onRowClickListener = onRowClickListener;
+ if (this.onRowClickListener != null) {
+ setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onClick(Column column, String value, Object o, int col, int row) {
+ TableData.this.onRowClickListener.onClick(column, t.get(row), col, row);
+ }
+ });
+ }
+
+ }
+
+
+ /**
+ * 设置表格列点击事件
+ */
+ public void setOnColumnClickListener(final OnColumnClickListener onColumnClickListener) {
+ this.onColumnClickListener = onColumnClickListener;
+ if (this.onRowClickListener != null) {
+ setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onClick(Column column, String value, Object o, int col, int row) {
+ TableData.this.onColumnClickListener.onClick(column, column.getDatas(), col, row);
+ }
+ });
+ }
+ }
+
+
+ public OnRowClickListener getOnRowClickListener() {
+ return onRowClickListener;
+ }
+
+ /**
+ * 表格单元格Cell点击事件接口
+ */
+ public interface OnItemClickListener {
+ void onClick(Column column, String value, T t, int col, int row);
+ }
+
+ /**
+ * 表格行点击事件接口
+ */
+ public interface OnRowClickListener {
+ void onClick(Column column, T t, int col, int row);
+ }
+
+ public interface OnColumnClickListener {
+ void onClick(Column column, List t, int col, int row);
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/TableInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/TableInfo.java
new file mode 100755
index 000000000..aa9a707ad
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/bean/TableInfo.java
@@ -0,0 +1,179 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.bean;
+
+import android.graphics.Rect;
+
+public class TableInfo {
+
+ private int topHeight;
+ private int titleHeight;
+ private int tableTitleSize;
+ private int yAxisWidth;
+ private int countHeight;
+ private int titleDirection;
+ private Rect tableRect;
+ private int maxLevel = 1;
+ private int columnSize;
+ private int[] lineHeightArray;
+ private float zoom = 1;
+ private Cell[][] rangeCells;
+ private int lineSize;
+
+ /**
+ * 获取最大层级
+ *
+ * @return 最大层级
+ */
+ public int getMaxLevel() {
+ return maxLevel;
+ }
+
+ /**
+ * 设置最大层级
+ * 该方法提供用于表格递归
+ *
+ * @return 最大层级
+ */
+ public void setMaxLevel(int maxLevel) {
+ this.maxLevel = maxLevel;
+ }
+
+ /**
+ * 获取列总数
+ *
+ * @return 列总数
+ */
+ public int getColumnSize() {
+ return columnSize;
+ }
+
+ public void setColumnSize(int columnSize) {
+ this.columnSize = columnSize;
+ rangeCells = new Cell[lineSize][columnSize];
+
+ }
+
+ public int getTopHeight() {
+ return topHeight;
+ }
+
+ public int getTopHeight(float zoom) {
+ return (int) (topHeight * zoom);
+ }
+
+ public void setTopHeight(int topHeight) {
+ this.topHeight = topHeight;
+ }
+
+ public int getTitleHeight() {
+ return (int) (titleHeight * zoom);
+ }
+
+ public void setTitleHeight(int titleHeight) {
+ this.titleHeight = titleHeight;
+ }
+
+
+ public Rect getTableRect() {
+ return tableRect;
+ }
+
+ public void setTableRect(Rect tableRect) {
+ this.tableRect = tableRect;
+ }
+
+ public int getyAxisWidth() {
+ return yAxisWidth;
+ }
+
+
+ public void setLineSize(int lineSize) {
+ this.lineSize = lineSize;
+ this.lineHeightArray = new int[lineSize];
+
+ }
+
+ /**
+ * 动态添加列,数组重新创建Copy
+ *
+ * @param count 添加数量
+ */
+ public void addLine(int count, boolean isFoot) {
+ lineSize += count;
+ int size = lineHeightArray.length;
+ int[] tempArray = new int[size + count];
+ //数组复制
+ if (isFoot) {
+ System.arraycopy(lineHeightArray, 0, tempArray, 0, size);
+ } else {
+ System.arraycopy(lineHeightArray, 0, tempArray, count, size);
+ }
+ lineHeightArray = tempArray;
+ if (size == rangeCells.length) {
+ Cell[][] tempRangeCells = new Cell[size + count][columnSize];
+ for (int i = 0; i < size; i++) {
+ tempRangeCells[i + (isFoot ? 0 : count)] = rangeCells[i];
+ }
+ rangeCells = tempRangeCells;
+ }
+ }
+
+ public int getCountHeight() {
+ return (int) (zoom * countHeight);
+ }
+
+ public void setCountHeight(int countHeight) {
+ this.countHeight = countHeight;
+ }
+
+
+ public int[] getLineHeightArray() {
+ return lineHeightArray;
+ }
+
+ /**
+ * 获取缩放值
+ *
+ * @return 缩放值
+ */
+ public float getZoom() {
+ return zoom;
+ }
+
+ /**
+ * 设置缩放值
+ */
+ public void setZoom(float zoom) {
+ this.zoom = zoom;
+ }
+
+ public void setyAxisWidth(int yAxisWidth) {
+ this.yAxisWidth = yAxisWidth;
+ }
+
+ public int getTableTitleSize() {
+ return tableTitleSize;
+ }
+
+ public void setTableTitleSize(int tableTitleSize) {
+ this.tableTitleSize = tableTitleSize;
+ }
+
+ public int getTitleDirection() {
+ return titleDirection;
+ }
+
+ public void setTitleDirection(int titleDirection) {
+ this.titleDirection = titleDirection;
+ }
+
+ public Cell[][] getRangeCells() {
+ return rangeCells;
+ }
+
+ public void clear() {
+ rangeCells = null;
+ lineHeightArray = null;
+ tableRect = null;
+ }
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/SmartTable.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/SmartTable.java
new file mode 100755
index 000000000..196774faa
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/SmartTable.java
@@ -0,0 +1,578 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.component;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.MatrixHelper;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableMeasurer;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableParser;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableProvider;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IComponent;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ISelectFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ITableTitle;
+import com.didichuxing.doraemonkit.ui.widget.tableview.listener.OnColumnClickListener;
+import com.didichuxing.doraemonkit.ui.widget.tableview.listener.OnTableChangeListener;
+import com.didichuxing.doraemonkit.ui.widget.tableview.style.FontStyle;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class SmartTable extends View implements OnTableChangeListener {
+
+ private YSequence yAxis;
+ private ITableTitle tableTitle;
+ private TableProvider provider;
+ private Rect showRect;
+ private Rect tableRect;
+ private TableConfig config = TableConfig.getInstance();
+ private TableParser parser;
+ private TableData tableData;
+ private int defaultHeight = 300;
+ private int defaultWidth = 300;
+ private TableMeasurer measurer;
+ protected Paint paint;
+ private MatrixHelper matrixHelper;
+ private boolean isExactly = true; //是否是测量精准模式
+ private AtomicBoolean isNotifying = new AtomicBoolean(false); //是否正在更新数据
+ private boolean isYSequenceRight;
+
+
+ public SmartTable(Context context) {
+ super(context);
+ init();
+ }
+
+ public SmartTable(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public SmartTable(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ /**
+ * 初始化
+ */
+ private void init() {
+ FontStyle.setDefaultTextSpSize(getContext(), 13);
+ paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ showRect = new Rect();
+ tableRect = new Rect();
+ yAxis = new YSequence<>();
+ parser = new TableParser<>();
+ provider = new TableProvider<>();
+ config.setPaint(paint);
+ measurer = new TableMeasurer<>();
+ tableTitle = new TableTitle();
+ tableTitle.setDirection(IComponent.TOP);
+ matrixHelper = new MatrixHelper(getContext());
+ matrixHelper.setOnTableChangeListener(this);
+ matrixHelper.register(provider);
+ matrixHelper.setOnInterceptListener(provider.getOperation());
+
+ }
+
+ /**
+ * 绘制
+ * 首先通过计算的table大小,计算table title大小
+ * 再通过 matrixHelper getZoomProviderRect计算实现缩放和位移的Rect
+ * 再绘制背景
+ * 绘制XY序号列
+ * 最后绘制内容
+ *
+ * @param canvas
+ */
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (!isNotifying.get()) {
+ setScrollY(0);
+ showRect.set(getPaddingLeft(), getPaddingTop(),
+ getWidth() - getPaddingRight(),
+ getHeight() - getPaddingBottom());
+ if (tableData != null) {
+ //表格Rect
+ Rect rect = tableData.getTableInfo().getTableRect();
+ if (rect != null) {
+ if (config.isShowTableTitle()) {
+ measurer.measureTableTitle(tableData, tableTitle, showRect);
+ }
+ tableRect.set(rect);
+ Rect scaleRect = matrixHelper.getZoomProviderRect(showRect, tableRect,
+ tableData.getTableInfo());
+ if (config.isShowTableTitle()) {
+ tableTitle.onMeasure(scaleRect, showRect, config);
+ tableTitle.onDraw(canvas, showRect, tableData.getTableName(), config);
+ }
+ if (config.isShowYSequence()) {
+ yAxis.onMeasure(scaleRect, showRect, config);
+ if (isYSequenceRight) {
+ canvas.save();
+ canvas.translate(showRect.width(), 0);
+ yAxis.onDraw(canvas, showRect, tableData, config);
+ canvas.restore();
+ } else {
+ yAxis.onDraw(canvas, showRect, tableData, config);
+ }
+ }
+ if (isYSequenceRight) {
+ canvas.save();
+ canvas.translate(-yAxis.getWidth(), 0);
+ provider.onDraw(canvas, scaleRect, showRect, tableData);
+ canvas.restore();
+ } else {
+ provider.onDraw(canvas, scaleRect, showRect, tableData);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 绘制表格边框背景
+ *
+ * @param canvas
+ */
+ private void drawGridBackground(Canvas canvas, Rect showRect, Rect scaleRect) {
+ config.contentGridStyle.fillPaint(paint);
+ canvas.drawRect(Math.max(showRect.left, scaleRect.left),
+ Math.max(showRect.top, scaleRect.top),
+ Math.min(showRect.right, scaleRect.right),
+ Math.min(scaleRect.bottom, showRect.bottom), paint);
+ }
+
+ /**
+ * 获取表格配置
+ * 可以使用TableConfig进行样式的配置,包括颜色,是否固定,开启统计行等
+ *
+ * @return 表格配置
+ */
+ public TableConfig getConfig() {
+ return config;
+ }
+
+ /**
+ * 设置表格数据
+ *
+ * @param tableData
+ */
+ public void setTableData(TableData tableData) {
+ if (tableData != null) {
+ this.tableData = tableData;
+ notifyDataChanged();
+ }
+ }
+
+ public ITableTitle getTableTitle() {
+ return tableTitle;
+ }
+
+ /**
+ * 通知更新
+ */
+ public void notifyDataChanged() {
+
+ if (tableData != null) {
+ config.setPaint(paint);
+ //开启线程
+ isNotifying.set(true);
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ //long start = System.currentTimeMillis();
+ parser.parse(tableData);
+ TableInfo info = measurer.measure(tableData, getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
+ yAxis.setWidth(info.getyAxisWidth());
+ requestReMeasure();
+ postInvalidate();
+ isNotifying.set(false);
+ //long end = System.currentTimeMillis();
+ //Log.e("smartTable","notifyDataChanged timeMillis="+(end-start));
+ }
+
+ }).start();
+
+ }
+ }
+
+ /**
+ * 添加数据
+ * 通过这个方法可以实现动态添加数据,参数isFoot可以实现首尾添加
+ *
+ * @param t 新增数据
+ * @param isFoot 是否在尾部添加
+ */
+ public void addData(final List t, final boolean isFoot) {
+ if (t != null && t.size() > 0) {
+ isNotifying.set(true);
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ parser.addData(tableData, t, isFoot);
+ measurer.measure(tableData, getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
+ requestReMeasure();
+ postInvalidate();
+ isNotifying.set(false);
+
+ }
+ }).start();
+ }
+ }
+
+
+ /**
+ * 通知重绘
+ * 增加锁机制,避免闪屏和数据更新异常
+ */
+ @Override
+ public void invalidate() {
+ if (!isNotifying.get()) {
+ super.invalidate();
+ }
+
+ }
+
+ /**
+ * 通知重新测量大小
+ */
+ private void requestReMeasure() {
+ //不是精准模式 且已经测量了
+ if (!isExactly && getMeasuredHeight() != 0 && tableData != null) {
+ if (tableData.getTableInfo().getTableRect() != null) {
+ int defaultHeight = tableData.getTableInfo().getTableRect().height()
+ + getPaddingTop();
+ int defaultWidth = tableData.getTableInfo().getTableRect().width();
+ int[] realSize = new int[2];
+ getLocationInWindow(realSize);
+ DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
+ int screenWidth = dm.widthPixels;
+ int screenHeight = dm.heightPixels;
+ int maxWidth = screenWidth - realSize[0];
+ int maxHeight = screenHeight - realSize[1];
+ defaultHeight = Math.min(defaultHeight, maxHeight);
+ defaultWidth = Math.min(defaultWidth, maxWidth);
+ if (this.defaultHeight != defaultHeight
+ || this.defaultWidth != defaultWidth) {
+ this.defaultHeight = defaultHeight;
+ this.defaultWidth = defaultWidth;
+ post(new Runnable() {
+ @Override
+ public void run() {
+ requestLayout();
+ }
+ });
+
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
+ requestReMeasure();
+ }
+
+ /**
+ * 计算组件宽度
+ */
+
+ private int measureWidth(int widthMeasureSpec) {
+ int result;
+ int specMode = MeasureSpec.getMode(widthMeasureSpec);
+ int specSize = MeasureSpec.getSize(widthMeasureSpec);
+ if (specMode == MeasureSpec.EXACTLY) {//精确模式
+ result = specSize;
+ } else {
+ isExactly = false;
+ result = defaultWidth;//最大尺寸模式,getDefaultWidth方法需要我们根据控件实际需要自己实现
+ if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 计算组件高度
+ */
+
+ private int measureHeight(int measureSpec) {
+
+ int result;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+ if (specMode == MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else {
+ isExactly = false;
+ result = defaultHeight;
+ if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 将触摸事件交给Iouch处理
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return matrixHelper.handlerTouchEvent(event);
+ }
+
+ /**
+ * 分发事件
+ * 在这里会去调用MatrixHelper onDisallowInterceptEvent方法
+ * 判断是否阻止parent拦截自己的事件
+ *
+ * @param event
+ * @return
+ */
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ matrixHelper.onDisallowInterceptEvent(this, event);
+ return super.dispatchTouchEvent(event);
+ }
+
+
+ /**
+ * 表格移动缩放改变回调
+ *
+ * @param scale 缩放值
+ * @param translateX X位移值
+ * @param translateY Y位移值
+ */
+ @Override
+ public void onTableChanged(float scale, float translateX, float translateY) {
+ if (tableData != null) {
+ config.setZoom(scale);
+ tableData.getTableInfo().setZoom(scale);
+ invalidate();
+ }
+ }
+
+ /**
+ * 获取列点击事件
+ */
+ public OnColumnClickListener getOnColumnClickListener() {
+ return provider.getOnColumnClickListener();
+ }
+
+ /**
+ * 设置列点击事件,实现对列的监听
+ *
+ * @param onColumnClickListener 列点击事件
+ */
+ public void setOnColumnClickListener(OnColumnClickListener onColumnClickListener) {
+ this.provider.setOnColumnClickListener(onColumnClickListener);
+ }
+
+ /**
+ * 列排序
+ * 你可以调用这个方法,对所有数据进行排序,排序根据设置的column排序
+ *
+ * @param column 列
+ * @param isReverse 是否反序
+ */
+ public void setSortColumn(Column column, boolean isReverse) {
+ if (tableData != null && column != null) {
+ tableData.setSortColumn(column);
+ setTableData(tableData);
+ }
+ }
+
+ public Rect getShowRect() {
+ return showRect;
+ }
+
+
+ /**
+ * 获取绘制表格内容者
+ *
+ * @return 绘制表格内容者
+ */
+ public TableProvider getProvider() {
+ return provider;
+ }
+
+
+ /**
+ * 获取表格数据
+ * TableData是解析数据之后对数据的封装对象,包含table column,rect等信息
+ *
+ * @return 表格数据
+ */
+ public TableData getTableData() {
+ return tableData;
+ }
+
+
+ /**
+ * 开启缩放
+ *
+ * @param zoom 是否缩放
+ */
+ public void setZoom(boolean zoom) {
+
+ matrixHelper.setCanZoom(zoom);
+ invalidate();
+
+ }
+
+ /**
+ * 开启缩放设置缩放值
+ *
+ * @param zoom 是否缩放
+ * @param maxZoom 最大缩放值
+ * @param minZoom 最小缩放值
+ */
+ public void setZoom(boolean zoom, float maxZoom, float minZoom) {
+
+ matrixHelper.setCanZoom(zoom);
+ matrixHelper.setMinZoom(minZoom);
+ matrixHelper.setMaxZoom(maxZoom);
+ invalidate();
+
+ }
+
+
+ /**
+ * 获取缩放移动辅助类
+ * 如果你需要更多的移动功能,可以使用它
+ *
+ * @return 缩放移动辅助类
+ */
+ public MatrixHelper getMatrixHelper() {
+ return matrixHelper;
+ }
+
+
+ /**
+ * 设置选中格子格式化
+ *
+ * @param selectFormat 选中格子格式化
+ */
+ public void setSelectFormat(ISelectFormat selectFormat) {
+ this.provider.setSelectFormat(selectFormat);
+ }
+
+
+ @Override
+ public int computeHorizontalScrollRange() {
+ final int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight();
+ int scrollRange = matrixHelper.getZoomRect().right;
+ final int scrollX = -matrixHelper.getZoomRect().right;
+ final int overScrollRight = Math.max(0, scrollRange - contentWidth);
+ if (scrollX < 0) {
+ scrollRange -= scrollX;
+ } else if (scrollX > overScrollRight) {
+ scrollRange += scrollX - overScrollRight;
+ }
+ return scrollRange;
+ }
+
+ @Override
+ public boolean canScrollVertically(int direction) {
+ if (direction < 0) {
+ return matrixHelper.getZoomRect().top != 0;
+ } else {
+ return matrixHelper.getZoomRect().bottom > matrixHelper.getOriginalRect().bottom;
+ }
+
+ }
+
+ @Override
+ public int computeHorizontalScrollOffset() {
+ return Math.max(0, -matrixHelper.getZoomRect().top);
+ }
+
+
+ @Override
+ public int computeHorizontalScrollExtent() {
+ return super.computeHorizontalScrollExtent();
+ }
+
+ @Override
+ public int computeVerticalScrollRange() {
+
+ final int contentHeight = getHeight() - getPaddingBottom() - getPaddingTop();
+ int scrollRange = matrixHelper.getZoomRect().bottom;
+ final int scrollY = -matrixHelper.getZoomRect().left;
+ final int overScrollBottom = Math.max(0, scrollRange - contentHeight);
+ if (scrollY < 0) {
+ scrollRange -= scrollY;
+ } else if (scrollY > overScrollBottom) {
+ scrollRange += scrollY - overScrollBottom;
+ }
+
+ return scrollRange;
+ }
+
+ @Override
+ public int computeVerticalScrollOffset() {
+
+ return Math.max(0, -matrixHelper.getZoomRect().left);
+ }
+
+ @Override
+ public int computeVerticalScrollExtent() {
+
+ return super.computeVerticalScrollExtent();
+
+ }
+
+ public YSequence getYSequence() {
+ return yAxis;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (tableData != null && getContext() != null) {
+ if (((Activity) getContext()).isFinishing()) {
+ release();
+ }
+ }
+ }
+
+ /**
+ * 可以在Activity onDestroy释放
+ */
+ private void release() {
+ matrixHelper.unRegisterAll();
+ measurer = null;
+ provider = null;
+ matrixHelper = null;
+ provider = null;
+ if (tableData != null) {
+ tableData.clear();
+ tableData = null;
+ }
+ yAxis = null;
+ }
+
+ public boolean isYSequenceRight() {
+ return isYSequenceRight;
+ }
+
+ public void setYSequenceRight(boolean YSequenceRight) {
+ isYSequenceRight = YSequenceRight;
+ }
+}
+
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/TableTitle.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/TableTitle.java
new file mode 100755
index 000000000..bee411c6b
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/TableTitle.java
@@ -0,0 +1,97 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.component;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ITableTitle;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+
+public class TableTitle implements ITableTitle {
+
+ private int size = 100;
+ private Rect rect = new Rect();
+ protected int direction;
+
+
+ @Override
+ public void onDraw(Canvas canvas, Rect showRect, String tableName, TableConfig config) {
+ Paint paint = config.getPaint();
+ config.tableTitleStyle.fillPaint(paint);
+ Rect rect = getRect();
+ int startX = rect.centerX();
+ Path path = new Path();
+ switch (direction) {
+ case TOP:
+ case BOTTOM:
+ DrawUtils.drawMultiText(canvas, paint, rect, tableName.split("\n"));
+ break;
+ case LEFT:
+ case RIGHT:
+ int textWidth = (int) paint.measureText(tableName);
+ path.moveTo(startX, rect.top);
+ path.lineTo(startX, rect.bottom);
+ canvas.drawTextOnPath(tableName, path, textWidth / 2, 0, paint);
+ break;
+ }
+ }
+
+ @Override
+ public void onMeasure(Rect scaleRect, Rect showRect, TableConfig config) {
+ rect.left = showRect.left;
+ rect.right = showRect.right;
+ rect.top = showRect.top;
+ rect.bottom = Math.min(showRect.bottom, scaleRect.bottom);
+ int h = size;
+ int w = size;
+ switch (direction) {
+ case TOP:
+ rect.bottom = rect.top + h;
+ scaleRect.top += h;
+ showRect.top += h;
+ break;
+ case LEFT:
+ rect.right = rect.left + w;
+ scaleRect.left += w;
+ showRect.left += w;
+ break;
+ case RIGHT:
+ rect.left = rect.right - w;
+ scaleRect.right -= w;
+ showRect.right -= w;
+ break;
+ case BOTTOM:
+ rect.top = rect.bottom - h;
+ scaleRect.bottom -= h;
+ showRect.bottom -= h;
+ break;
+ }
+ }
+
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ public Rect getRect() {
+ return rect;
+ }
+
+ public void setRect(Rect rect) {
+ this.rect = rect;
+ }
+
+ public int getDirection() {
+ return direction;
+ }
+
+ public void setDirection(int direction) {
+ this.direction = direction;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/YSequence.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/YSequence.java
new file mode 100755
index 000000000..37839a422
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/component/YSequence.java
@@ -0,0 +1,172 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.component;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableData;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.TableInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IComponent;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ISequenceFormat;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+
+public class YSequence implements IComponent> {
+
+ private Rect rect;
+ private int width;
+ private int clipWidth;
+ private Rect scaleRect;
+ private ISequenceFormat format;
+ private Rect tempRect; //临时使用
+
+ public YSequence() {
+ rect = new Rect();
+ tempRect = new Rect();
+ }
+
+ @Override
+ public void onMeasure(Rect scaleRect, Rect showRect, TableConfig config) {
+ this.scaleRect = scaleRect;
+ int scaleWidth = (int) (width * (config.getZoom() > 1 ? 1 : config.getZoom()));
+ boolean fixed = config.isFixedYSequence();
+ rect.top = scaleRect.top;
+ rect.bottom = scaleRect.bottom;
+ rect.left = fixed ? showRect.left : scaleRect.left;
+ rect.right = rect.left + scaleWidth;
+ if (fixed) {
+ scaleRect.left += scaleWidth;
+ showRect.left += scaleWidth;
+ clipWidth = scaleWidth;
+ } else {
+ int disX = showRect.left - scaleRect.left;
+ clipWidth = Math.max(0, scaleWidth - disX);
+ showRect.left += clipWidth;
+ scaleRect.left += scaleWidth;
+ }
+ }
+
+ @Override
+ public void onDraw(Canvas canvas, Rect showRect, TableData tableData, TableConfig config) {
+ format = tableData.getYSequenceFormat();
+ float hZoom = (config.getZoom() > 1 ? 1 : config.getZoom());
+ int totalSize = tableData.getLineSize();
+ TableInfo info = tableData.getTableInfo();
+ int topHeight = info.getTopHeight(hZoom);
+ float top = rect.top + topHeight;
+ int showLeft = showRect.left - clipWidth;
+ boolean isFixTop = config.isFixedXSequence();
+ int showTop = isFixTop ? (showRect.top + topHeight) : showRect.top;
+ float tempTop = top;
+ boolean isFixedTitle = config.isFixedTitle();
+ boolean isFixedCount = config.isFixedCountRow();
+ if (isFixedTitle) {
+ int clipHeight;
+ if (isFixTop) {
+ clipHeight = info.getTopHeight(hZoom);
+ } else {
+ int disY = showRect.top - scaleRect.top;
+ clipHeight = Math.max(0, topHeight - disY);
+ }
+ tempTop = showRect.top + clipHeight;
+ }
+
+ tempRect.set(showLeft, (int) tempTop - topHeight, showRect.left, (int) tempTop);
+ drawLeftAndTop(canvas, showRect, tempRect, config);
+ canvas.save();
+ canvas.clipRect(showLeft, showTop,
+ showRect.left, showRect.bottom);
+ if (config.isShowColumnTitle()) {
+ for (int i = 0; i < info.getMaxLevel(); i++) {
+ float bottom = tempTop + info.getTitleHeight();
+ if (DrawUtils.isVerticalMixRect(showRect, (int) top, (int) bottom)) {
+ tempRect.set(rect.left, (int) tempTop, rect.right, (int) bottom);
+ drawRect(canvas, tempRect, config);
+ }
+ tempTop = bottom;
+ top += info.getTitleHeight();
+ }
+ }
+ int tempBottom = showRect.bottom;
+ if (isFixedTitle || isFixedCount) {
+ canvas.save();
+ canvas.clipRect(showLeft, tempTop, showRect.left, tempBottom);
+ }
+ int num = 0;
+ for (int i = 0; i < totalSize; i++) {
+ num++;
+ float bottom = top + info.getLineHeightArray()[i] * config.getZoom();
+ if (showRect.bottom >= rect.top) {
+ if (DrawUtils.isVerticalMixRect(showRect, (int) top, (int) bottom)) {
+ tempRect.set(rect.left, (int) top, rect.right, (int) bottom);
+ draw(canvas, tempRect, num, config);
+ }
+ } else {
+ break;
+ }
+ top = bottom;
+ }
+ if (isFixedTitle || isFixedCount) {
+ canvas.restore();
+ }
+ canvas.restore();
+
+ }
+
+ /**
+ * 绘制左上角空隙
+ *
+ * @param canvas
+ * @param rect
+ * @param config
+ */
+ private void drawLeftAndTop(Canvas canvas, Rect showRect, Rect rect, TableConfig config) {
+ canvas.save();
+ canvas.clipRect(Math.max(this.rect.left, rect.left), showRect.top,
+ showRect.left, rect.bottom);
+ Paint paint = config.getPaint();
+ if (config.getLeftAndTopBackgroundColor() != 0) {
+ paint.setStyle(Paint.Style.FILL);
+ paint.setColor(config.getLeftAndTopBackgroundColor());
+ canvas.drawRect(rect, paint);
+ }
+
+ config.SequenceGridStyle.fillPaint(paint);
+ canvas.drawRect(rect, paint);
+
+ canvas.restore();
+ }
+
+ private void draw(Canvas canvas, Rect rect, int position, TableConfig config) {
+ drawRect(canvas, rect, config);
+ format.draw(canvas, position - 1, rect, config);
+ }
+
+ private void drawRect(Canvas canvas, Rect rect, TableConfig config) {
+ Paint paint = config.getPaint();
+ int textColor = TableConfig.INVALID_COLOR;
+
+ config.SequenceGridStyle.fillPaint(paint);
+ canvas.drawRect(rect, paint);
+
+ config.YSequenceStyle.fillPaint(paint);
+
+ if (textColor != TableConfig.INVALID_COLOR) {
+ paint.setColor(textColor);
+ }
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public Rect getRect() {
+ return rect;
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/BaseSequenceFormat.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/BaseSequenceFormat.java
new file mode 100644
index 000000000..b19fd93f5
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/BaseSequenceFormat.java
@@ -0,0 +1,20 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.format;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ISequenceFormat;
+
+public abstract class BaseSequenceFormat implements ISequenceFormat {
+ @Override
+ public void draw(Canvas canvas, int sequence, Rect rect, TableConfig config) {
+ //字体缩放
+ Paint paint = config.getPaint();
+ paint.setTextSize(paint.getTextSize() * (config.getZoom() > 1 ? 1 : config.getZoom()));
+ paint.setTextAlign(Paint.Align.CENTER);
+ canvas.drawText(format(sequence + 1), rect.centerX(), DrawUtils.getTextCenterY(rect.centerY(), paint), paint);
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/FastTextDrawFormat.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/FastTextDrawFormat.java
new file mode 100644
index 000000000..5fb4ed22d
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/FastTextDrawFormat.java
@@ -0,0 +1,61 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.format;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+
+import java.util.HashMap;
+
+
+public class FastTextDrawFormat extends TextDrawFormat {
+
+
+ private String HEIGHT_KEY = "dk_height";
+ private HashMap cacheMap = new HashMap<>();
+
+ @Override
+
+ public int measureWidth(Column column, int position) {
+ int width = 0;
+ String value = column.format(position);
+ Integer maxLengthValue = cacheMap.get(column.getColumnName());
+ if (maxLengthValue == null) {
+ width = comperLength(column, value);
+ } else if (value.length() > maxLengthValue) {
+ width = comperLength(column, value);
+ }
+ return width;
+ }
+
+ private int comperLength(Column column, String value) {
+ TableConfig config = TableConfig.getInstance();
+ Paint paint = config.getPaint();
+ config.contentStyle.fillPaint(paint);
+ cacheMap.put(column.getColumnName(), value.length());
+ return (int) paint.measureText(value);
+ }
+
+ @Override
+ public int measureHeight(Column column, int position) {
+ int height;
+ if (cacheMap.get(HEIGHT_KEY) == null) {
+ TableConfig config = TableConfig.getInstance();
+ Paint paint = config.getPaint();
+ config.contentStyle.fillPaint(paint);
+ cacheMap.put(HEIGHT_KEY, DrawUtils.getTextHeight(paint));
+ }
+ height = cacheMap.get(HEIGHT_KEY);
+ return height;
+ }
+
+
+ protected void drawText(Canvas c, String value, Rect rect, Paint paint) {
+ DrawUtils.drawSingleText(c, paint, rect, value);
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/NumberSequenceFormat.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/NumberSequenceFormat.java
new file mode 100644
index 000000000..8262ecfaf
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/NumberSequenceFormat.java
@@ -0,0 +1,12 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.format;
+
+
+public class NumberSequenceFormat extends BaseSequenceFormat {
+
+ @Override
+ public String format(Integer position) {
+ return String.valueOf(position);
+ }
+
+
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/TextDrawFormat.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/TextDrawFormat.java
new file mode 100644
index 000000000..233ae1a91
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/TextDrawFormat.java
@@ -0,0 +1,81 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.format;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.Log;
+
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.CellInfo;
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.IDrawFormat;
+
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class TextDrawFormat implements IDrawFormat {
+
+
+ private Map> valueMap; //避免产生大量对象
+
+ public TextDrawFormat() {
+ valueMap = new HashMap<>();
+ }
+
+ @Override
+ public int measureWidth(Column column, int position) {
+
+ TableConfig config = TableConfig.getInstance();
+ Paint paint = config.getPaint();
+ config.contentStyle.fillPaint(paint);
+ return DrawUtils.getMultiTextWidth(paint, getSplitString(column.format(position)));
+ }
+
+
+ @Override
+ public int measureHeight(Column column, int position) {
+ TableConfig config = TableConfig.getInstance();
+ Paint paint = config.getPaint();
+ config.contentStyle.fillPaint(paint);
+ return DrawUtils.getMultiTextHeight(paint, getSplitString(column.format(position)));
+ }
+
+ @Override
+ public void draw(Canvas c, Rect rect, CellInfo cellInfo) {
+ TableConfig config = TableConfig.getInstance();
+ Paint paint = config.getPaint();
+ setTextPaint(config, cellInfo, paint);
+ if (cellInfo.column.getTextAlign() != null) {
+ paint.setTextAlign(cellInfo.column.getTextAlign());
+ }
+ drawText(c, cellInfo.value, rect, paint);
+ }
+
+ protected void drawText(Canvas c, String value, Rect rect, Paint paint) {
+ DrawUtils.drawMultiText(c, paint, rect, getSplitString(value));
+ }
+
+
+ public void setTextPaint(TableConfig config, CellInfo cellInfo, Paint paint) {
+ config.contentStyle.fillPaint(paint);
+ paint.setTextSize(paint.getTextSize() * config.getZoom());
+
+ }
+
+ protected String[] getSplitString(String val) {
+ String[] values = null;
+ if (valueMap.get(val) != null) {
+ values = valueMap.get(val).get();
+ }
+ if (values == null) {
+ values = val.split("\n");
+
+ valueMap.put(val, new SoftReference<>(values));
+ }
+ return values;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/TitleDrawFormat.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/TitleDrawFormat.java
new file mode 100644
index 000000000..ae7a8f26f
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/format/TitleDrawFormat.java
@@ -0,0 +1,56 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.format;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.bean.Column;
+import com.didichuxing.doraemonkit.ui.widget.tableview.utils.DrawUtils;
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+import com.didichuxing.doraemonkit.ui.widget.tableview.intface.ITitleDrawFormat;
+
+
+public class TitleDrawFormat implements ITitleDrawFormat {
+
+ private boolean isDrawBg;
+
+ @Override
+ public int measureWidth(Column column, TableConfig config) {
+ Paint paint = config.getPaint();
+ config.columnTitleStyle.fillPaint(paint);
+ return (int) (paint.measureText(column.getColumnName()));
+ }
+
+
+ @Override
+ public int measureHeight(TableConfig config) {
+ Paint paint = config.getPaint();
+ config.columnTitleStyle.fillPaint(paint);
+ return DrawUtils.getTextHeight(config.columnTitleStyle,config.getPaint());
+ }
+
+ @Override
+ public void draw(Canvas c, Column column, Rect rect, TableConfig config) {
+ Paint paint = config.getPaint();
+ config.columnTitleStyle.fillPaint(paint);
+
+ paint.setTextSize(paint.getTextSize()*config.getZoom());
+
+ drawText(c, column, rect, paint);
+ }
+
+ private void drawText(Canvas c, Column column, Rect rect, Paint paint) {
+ if(column.getTitleAlign() !=null) { //如果列设置Align ,则使用列的Align
+ paint.setTextAlign(column.getTitleAlign());
+ }
+ c.drawText(column.getColumnName(), DrawUtils.getTextCenterX(rect.left,rect.right,paint), DrawUtils.getTextCenterY((rect.bottom+rect.top)/2,paint) ,paint);
+ }
+
+ public boolean isDrawBg() {
+ return isDrawBg;
+ }
+
+ public void setDrawBg(boolean drawBg) {
+ isDrawBg = drawBg;
+ }
+}
diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/intface/IComponent.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/intface/IComponent.java
new file mode 100755
index 000000000..14480d9b8
--- /dev/null
+++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/tableview/intface/IComponent.java
@@ -0,0 +1,29 @@
+package com.didichuxing.doraemonkit.ui.widget.tableview.intface;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+import com.didichuxing.doraemonkit.ui.widget.tableview.TableConfig;
+
+public interface IComponent