diff --git a/.editorconfig b/.editorconfig index 191189ba4..53a4241f9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,8 +14,11 @@ ij_continuation_indent_size = 8 ij_java_doc_align_exception_comments = false ij_java_doc_align_param_comments = false -[*.{yaml,yml,sh,ps1}] +[*.{yaml, yml, sh, ps1}] indent_size = 2 -[*.{md,mkd,markdown}] +[*.{md, mkd, markdown}] trim_trailing_whitespace = false + +[{**/res/**.xml, **/AndroidManifest.xml}] +ij_continuation_indent_size = 4 diff --git a/android-test/app/build.gradle b/android-test/app/build.gradle index 6a19ba5da..ba3666c8a 100644 --- a/android-test/app/build.gradle +++ b/android-test/app/build.gradle @@ -4,15 +4,14 @@ plugins { } android { - compileSdk 32 + compileSdk 31 defaultConfig { applicationId "com.alibaba.fastjson2.android" minSdk 26 - targetSdk 26 + targetSdk 29 versionCode 1 versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -22,11 +21,15 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - namespace 'com.alibaba.fastjson2.android' + + buildFeatures { + viewBinding true + } } dependencies { @@ -41,7 +44,9 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.1' testImplementation 'junit:junit:5.8.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' -} \ No newline at end of file +} diff --git a/android-test/app/src/main/AndroidManifest.xml b/android-test/app/src/main/AndroidManifest.xml index 6c10807bc..6ef2a431c 100644 --- a/android-test/app/src/main/AndroidManifest.xml +++ b/android-test/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + + android:theme="@style/AppTheme"> + android:configChanges="orientation|screenSize|screenLayout" + android:exported="true" + android:launchMode="singleTask" + android:theme="@style/SplashTheme"> @@ -19,4 +23,4 @@ - \ No newline at end of file + diff --git a/android-test/app/src/main/assets/eishay.json b/android-test/app/src/main/assets/eishay.json new file mode 100644 index 000000000..08eed7916 --- /dev/null +++ b/android-test/app/src/main/assets/eishay.json @@ -0,0 +1,33 @@ +{ + "images": [ + { + "height": 768, + "size": "LARGE", + "title": "Javaone Keynote", + "uri": "http://javaone.com/keynote_large.jpg", + "width": 1024 + }, + { + "height": 240, + "size": "SMALL", + "title": "Javaone Keynote", + "uri": "http://javaone.com/keynote_small.jpg", + "width": 320 + } + ], + "media": { + "bitrate": 262144, + "duration": 18000000, + "format": "video/mpg4", + "height": 480, + "persons": [ + "Bill Gates", + "Steve Jobs" + ], + "player": "JAVA", + "size": 58982400, + "title": "Javaone Keynote", + "uri": "http://javaone.com/keynote.mpg", + "width": 640 + } +} diff --git a/android-test/app/src/main/ic_launcher-playstore.png b/android-test/app/src/main/ic_launcher-playstore.png new file mode 100644 index 000000000..199dd2131 Binary files /dev/null and b/android-test/app/src/main/ic_launcher-playstore.png differ diff --git a/android-test/app/src/main/java/com/alibaba/fastjson2/android/MainActivity.java b/android-test/app/src/main/java/com/alibaba/fastjson2/android/MainActivity.java index 2e80d9b57..111119a73 100644 --- a/android-test/app/src/main/java/com/alibaba/fastjson2/android/MainActivity.java +++ b/android-test/app/src/main/java/com/alibaba/fastjson2/android/MainActivity.java @@ -1,68 +1,228 @@ package com.alibaba.fastjson2.android; -import android.content.res.AssetManager; import android.os.Bundle; import android.util.Log; -import android.view.View; +import android.widget.CheckBox; import android.widget.RadioButton; -import android.widget.TextView; +import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.android.eishay.MediaContent; +import com.alibaba.fastjson2.android.databinding.ActivityMainBinding; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; -import java.io.BufferedReader; -import java.io.InputStreamReader; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; +import java.util.function.Function; public class MainActivity extends AppCompatActivity { static final int SERDE_LOOP_COUNT = 10_000; static final int PARSE_LOOP_COUNT = 1000; - Gson g = new Gson(); - ObjectMapper objectMapper = new ObjectMapper(); + static final String[] LIB_NAMES = { + "fastjson2", "fastjson1", "gson", "jackson" + }; + + static final String[] TAG_NAMES = { + "SERDE", "PARSE" + }; + + static final String[] ITEM_NAMES = { + "eishay", "cart", "homepage", "h5 api" + }; + + private Gson gson; + private ObjectMapper mapper; + + private final String[] texts = new String[ITEM_NAMES.length]; + private final StringBuilder result = new StringBuilder(128); + private Map>> tester; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + ActivityMainBinding inflate = + ActivityMainBinding.inflate( + getLayoutInflater() + ); + setContentView(inflate.getRoot()); - CART_STR = readString("cart.json"); - HOMEPAGE_STR = readString("homepage.json"); - H5API_STR = readString("h5api.json"); + int white = getResources().getColor( + R.color.white, null + ); - setContentView(R.layout.activity_main); - } + CheckBox[] libBoxes = new CheckBox[LIB_NAMES.length]; + for (int i = 0; i < LIB_NAMES.length; i++) { + CheckBox box = new CheckBox(this); + libBoxes[i] = box; + box.setChecked(i == 0); + box.setTag(LIB_NAMES[i]); + box.setText(LIB_NAMES[i]); + box.setTextColor(white); + inflate.libs.addView(box); + } - private String readString(String path) { - StringBuffer buffer = new StringBuffer(); - AssetManager assets = getApplicationContext().getAssets(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(assets.open(path), "utf-8"))) { - String line; - while ((line = reader.readLine()) != null) { - buffer.append(line); + RadioButton[] tagRadios = new RadioButton[TAG_NAMES.length]; + for (int i = 0; i < TAG_NAMES.length; i++) { + RadioButton radio = new RadioButton(this); + tagRadios[i] = radio; + radio.setTag(TAG_NAMES[i]); + radio.setText(TAG_NAMES[i]); + radio.setTextColor(white); + inflate.tags.addView(radio); + } + + RadioButton[] itemRadios = new RadioButton[ITEM_NAMES.length]; + for (int i = 0; i < ITEM_NAMES.length; i++) { + RadioButton radio = new RadioButton(this); + itemRadios[i] = radio; + radio.setTag(ITEM_NAMES[i]); + radio.setText(ITEM_NAMES[i]); + radio.setTextColor(white); + inflate.items.addView(radio); + } + + byte[] buffer = new byte[2048]; + ByteArrayOutputStream stream = new ByteArrayOutputStream(5120); + + String[] paths = { + "eishay.json", "cart.json", "homepage.json", "h5api.json" + }; + for (int i = 0; i < texts.length; i++) { + try (InputStream in = getResources().getAssets().open(paths[i]) + ) { + int size; + stream.reset(); + while ((size = in.read(buffer)) != -1) { + stream.write(buffer, 0, size); + } + } catch (Exception e) { + Log.d("Error getting resource", e.getMessage()); + } finally { + try { + texts[i] = stream.toString("UTF-8"); + } catch (UnsupportedEncodingException e) { + Log.d("Error getting resource", e.getMessage()); + } } - } catch (Exception e) { - Log.d("fastjson", e.getMessage()); } - return buffer.toString(); - } - private void appendInfo(String str) { - TextView textView10 = findViewById(R.id.textView); - String text = textView10.getText().toString(); - if (text.isEmpty()) { - text = str; - } else { - text = text + "\n" + str; + gson = new Gson(); + tester = new HashMap<>(); + mapper = new ObjectMapper(); + + { + Map> tags = new HashMap<>(); + tester.put("fastjson2", tags); + { + Map items = new HashMap<>(); + tags.put("SERDE", items); + items.put("eishay", this::fastjson2EishaySerde); + } + { + Map items = new HashMap<>(); + tags.put("PARSE", items); + for (int i = 0; i < ITEM_NAMES.length; i++) { + String text = texts[i]; + String item = ITEM_NAMES[i]; + items.put(item, () -> fastjson2Parse(text, item)); + } + } } - textView10.setText(text); - } + { + Map> tags = new HashMap<>(); + tester.put("fastjson1", tags); + { + Map items = new HashMap<>(); + tags.put("SERDE", items); + items.put("eishay", this::fastjson1EishaySerde); + } + { + Map items = new HashMap<>(); + tags.put("PARSE", items); + for (int i = 0; i < ITEM_NAMES.length; i++) { + String text = texts[i]; + String item = ITEM_NAMES[i]; + items.put(item, () -> fastjson1Parse(text, item)); + } + } + } + + { + Map> tags = new HashMap<>(); + tester.put("gson", tags); + { + Map items = new HashMap<>(); + tags.put("SERDE", items); + items.put("eishay", this::gsonEishaySerde); + } + } + + { + Map> tags = new HashMap<>(); + tester.put("jackson", tags); + { + Map items = new HashMap<>(); + tags.put("SERDE", items); + items.put("eishay", this::jacksonEishaySerde); + } + } + + Runnable updater = () -> inflate.result.setText(result); + ExecutorService executor = Executors.newCachedThreadPool(); + + Consumer consumer = + runnable -> executor.execute(() -> { + runnable.run(); + runOnUiThread(updater); + }); + Function target = radios -> { + for (RadioButton btn : radios) { + if (btn.isChecked()) { + return btn.getTag(); + + } + } + return null; + }; + + inflate.submit.setOnClickListener(v -> { + final Object tag = target.apply(tagRadios); + final Object item = target.apply(itemRadios); + + if (tag == null || item == null) { + Toast.makeText(this, "Unselected", Toast.LENGTH_SHORT).show(); + return; + } + + result.setLength(0); + inflate.result.setText( + result.append(tag).append(" ").append(item).append("\n\n") + ); + + Toast.makeText(this, "Testing", Toast.LENGTH_SHORT).show(); + for (CheckBox box : libBoxes) { + if (box.isChecked()) { + Optional.ofNullable(tester.get(box.getTag())) + .map((tags -> tags.get(tag))).map((items) -> items.get(item)).ifPresent(consumer); + } + } + }); + } public void fastjson1EishaySerde() { - MediaContent mediaContent = JSON.parseObject(EISHAY_STR, MediaContent.class); + MediaContent mediaContent = JSON.parseObject(texts[0], MediaContent.class); long toStringTotal; { long start = System.currentTimeMillis(); @@ -76,17 +236,19 @@ public class MainActivity extends AppCompatActivity { { long start = System.currentTimeMillis(); for (int i = 0; i < SERDE_LOOP_COUNT; i++) { - com.alibaba.fastjson.JSON.parseObject(EISHAY_STR, MediaContent.class); + com.alibaba.fastjson.JSON.parseObject(texts[0], MediaContent.class); } parseObjectTotal = System.currentTimeMillis() - start; } - appendInfo("fastjson1 serde : " + toStringTotal + ", " + parseObjectTotal); + synchronized (result) { + result.append("fastjson1 serde : ").append(toStringTotal).append(", ").append(parseObjectTotal).append("\n"); + } } public void fastjson2EishaySerde() { - MediaContent mediaContent = JSON.parseObject(EISHAY_STR, MediaContent.class); + MediaContent mediaContent = JSON.parseObject(texts[0], MediaContent.class); long toStringTotal; { @@ -101,42 +263,46 @@ public class MainActivity extends AppCompatActivity { { long start = System.currentTimeMillis(); for (int i = 0; i < SERDE_LOOP_COUNT; i++) { - JSON.parseObject(EISHAY_STR, MediaContent.class); + JSON.parseObject(texts[0], MediaContent.class); } parseObjectTotal = System.currentTimeMillis() - start; } - appendInfo("fastjson2 serde : " + toStringTotal + ", " + parseObjectTotal); + synchronized (result) { + result.append("fastjson2 serde : ").append(toStringTotal).append(", ").append(parseObjectTotal).append("\n"); + } } public void gsonEishaySerde() { - MediaContent mediaContent = JSON.parseObject(EISHAY_STR, MediaContent.class); + MediaContent mediaContent = JSON.parseObject(texts[0], MediaContent.class); long start = System.currentTimeMillis(); for (int i = 0; i < SERDE_LOOP_COUNT; i++) { - g.toJson(mediaContent); + gson.toJson(mediaContent); } long toStringTotal = System.currentTimeMillis() - start; start = System.currentTimeMillis(); for (int i = 0; i < SERDE_LOOP_COUNT; i++) { - g.fromJson(EISHAY_STR, MediaContent.class); + gson.fromJson(texts[0], MediaContent.class); } long parseObjectTotal = System.currentTimeMillis() - start; - appendInfo("gson serde : " + toStringTotal + ", " + parseObjectTotal); + synchronized (result) { + result.append("gson serde : ").append(toStringTotal).append(", ").append(parseObjectTotal).append("\n"); + } } public void jacksonEishaySerde() { - MediaContent mediaContent = JSON.parseObject(EISHAY_STR, MediaContent.class); + MediaContent mediaContent = JSON.parseObject(texts[0], MediaContent.class); try { long toStringTotal; { long start = System.currentTimeMillis(); for (int i = 0; i < SERDE_LOOP_COUNT; i++) { - objectMapper.writeValueAsString(mediaContent); + mapper.writeValueAsString(mediaContent); } toStringTotal = System.currentTimeMillis() - start; } @@ -145,38 +311,18 @@ public class MainActivity extends AppCompatActivity { { long start = System.currentTimeMillis(); for (int i = 0; i < SERDE_LOOP_COUNT; i++) { - objectMapper.readValue(EISHAY_STR, MediaContent.class); + mapper.readValue(texts[0], MediaContent.class); } parseObjectTotal = System.currentTimeMillis() - start; } - appendInfo("jackson serde : " + toStringTotal + ", " + parseObjectTotal); + synchronized (result) { + result.append("jackson serde : ").append(toStringTotal).append(", ").append(parseObjectTotal).append("\n"); + } } catch (Exception e) { - Log.d("fastjson", e.getMessage()); - } - } - - public void fastjson1Serde(View view) { - if (((RadioButton) findViewById(R.id.eishaySerde)).isChecked()) { - fastjson1EishaySerde(); - } - } - - public void fastjson2Serde(View view) { - if (((RadioButton) findViewById(R.id.eishaySerde)).isChecked()) { - fastjson2EishaySerde(); - } - } - - public void gsonSerde(View view) { - if (((RadioButton) findViewById(R.id.eishaySerde)).isChecked()) { - gsonEishaySerde(); - } - } - - public void jacksonSerde(View view) { - if (((RadioButton) findViewById(R.id.eishaySerde)).isChecked()) { - jacksonEishaySerde(); + synchronized (result) { + result.append("jackson error : ").append(e.getMessage()).append("\n"); + } } } @@ -186,7 +332,9 @@ public class MainActivity extends AppCompatActivity { com.alibaba.fastjson.JSON.parseObject(str); } long millis = System.currentTimeMillis() - start; - appendInfo("fastjson1 parse " + name + " : " + millis); + synchronized (result) { + result.append("fastjson1 parse ").append(name).append(" : ").append(millis).append("\n"); + } } public void fastjson2Parse(String str, String name) { @@ -195,7 +343,9 @@ public class MainActivity extends AppCompatActivity { JSON.parseObject(str); } long millis = System.currentTimeMillis() - start; - appendInfo("fastjson2 parse " + name + " : " + millis); + synchronized (result) { + result.append("fastjson2 parse ").append(name).append(" : ").append(millis).append("\n"); + } } public void orgjsonParse(String str, String name) { @@ -205,109 +355,13 @@ public class MainActivity extends AppCompatActivity { new org.json.JSONObject(str); } long millis = System.currentTimeMillis() - start; - appendInfo("orgjson parse " + name + " : " + millis); + synchronized (result) { + result.append("orgjson parse ").append(name).append(" : ").append(millis).append("\n"); + } } catch (Exception e) { - Log.d("fastjson", e.getMessage()); + synchronized (result) { + result.append("orgjson error : ").append(e.getMessage()).append("\n"); + } } } - - public void fastjson1Parse(View view) { - String str = null, name = null; - if (((RadioButton) findViewById(R.id.eishayParse)).isChecked()) { - str = EISHAY_STR; - name = "eishay"; - } else if (((RadioButton) findViewById(R.id.cartParse)).isChecked()) { - str = CART_STR; - name = "cart"; - } else if (((RadioButton) findViewById(R.id.homepageParse)).isChecked()) { - str = HOMEPAGE_STR; - name = "homepage"; - } else if (((RadioButton) findViewById(R.id.h5apiParse)).isChecked()) { - str = H5API_STR; - name = "h5api"; - } - if (str != null) { - fastjson1Parse(str, name); - } - } - - public void fastjson2Parse(View view) { - String str = null, name = null; - if (((RadioButton) findViewById(R.id.eishayParse)).isChecked()) { - str = EISHAY_STR; - name = "eishay"; - } else if (((RadioButton) findViewById(R.id.cartParse)).isChecked()) { - str = CART_STR; - name = "cart"; - } else if (((RadioButton) findViewById(R.id.homepageParse)).isChecked()) { - str = HOMEPAGE_STR; - name = "homepage"; - } else if (((RadioButton) findViewById(R.id.h5apiParse)).isChecked()) { - str = H5API_STR; - name = "h5api"; - } - if (str != null) { - fastjson2Parse(str, name); - } - } - - public void orgjsonParse(View view) { - String str = null, name = null; - if (((RadioButton) findViewById(R.id.eishayParse)).isChecked()) { - str = EISHAY_STR; - name = "eishay"; - } else if (((RadioButton) findViewById(R.id.cartParse)).isChecked()) { - str = CART_STR; - name = "cart"; - } else if (((RadioButton) findViewById(R.id.homepageParse)).isChecked()) { - str = HOMEPAGE_STR; - name = "homepage"; - } else if (((RadioButton) findViewById(R.id.h5apiParse)).isChecked()) { - str = H5API_STR; - name = "h5api"; - } - if (str != null) { - orgjsonParse(str, name); - } - } - - public void clear(View view) { - TextView textView10 = findViewById(R.id.textView); - textView10.setText(""); - } - - static final String EISHAY_STR = "{\"images\": [{\n" + - " \"height\":768,\n" + - " \"size\":\"LARGE\",\n" + - " \"title\":\"Javaone Keynote\",\n" + - " \"uri\":\"http://javaone.com/keynote_large.jpg\",\n" + - " \"width\":1024\n" + - " }, {\n" + - " \"height\":240,\n" + - " \"size\":\"SMALL\",\n" + - " \"title\":\"Javaone Keynote\",\n" + - " \"uri\":\"http://javaone.com/keynote_small.jpg\",\n" + - " \"width\":320\n" + - " }\n" + - " ],\n" + - " \"media\": {\n" + - " \"bitrate\":262144,\n" + - " \"duration\":18000000,\n" + - " \"format\":\"video/mpg4\",\n" + - " \"height\":480,\n" + - " \"persons\": [\n" + - " \"Bill Gates\",\n" + - " \"Steve Jobs\"\n" + - " ],\n" + - " \"player\":\"JAVA\",\n" + - " \"size\":58982400,\n" + - " \"title\":\"Javaone Keynote\",\n" + - " \"uri\":\"http://javaone.com/keynote.mpg\",\n" + - " \"width\":640\n" + - " }\n" + - "}"; - - static String CART_STR; - static String HOMEPAGE_STR; - static String H5API_STR; -} \ No newline at end of file +} diff --git a/android-test/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android-test/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d114..000000000 --- a/android-test/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/android-test/app/src/main/res/drawable/btn.xml b/android-test/app/src/main/res/drawable/btn.xml new file mode 100644 index 000000000..cf4d9cf95 --- /dev/null +++ b/android-test/app/src/main/res/drawable/btn.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/android-test/app/src/main/res/drawable/ic_launcher_background.xml b/android-test/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9cb..000000000 --- a/android-test/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android-test/app/src/main/res/layout/activity_main.xml b/android-test/app/src/main/res/layout/activity_main.xml index 3cd843ee3..c9f9932cd 100644 --- a/android-test/app/src/main/res/layout/activity_main.xml +++ b/android-test/app/src/main/res/layout/activity_main.xml @@ -1,133 +1,121 @@ - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/dark" + android:paddingStart="20dp" + android:paddingEnd="20dp" + tools:ignore="HardcodedText"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + app:layout_constraintGuide_percent="0.8" /> - - - - -