目录
- 一、 基础配置对比
-
- 1.依赖添加
- 2.布局定义
- 二、 折线图完整实现
-
- Kotlin 版本
- Java 版本
- 三、 饼图完整实现
-
- Kotlin 版本
- Java 版本
- 四、 高级功能实现
-
- 1.自定义 MarkerView
-
- Kotlin 版本
- Java 版本
-
- 限制线配置
-
- Kotlin 版本
- Java 版本
- 五、 性能优化实现
-
- 1.大数据量处理
-
- Kotlin 版本
- Java 版本
-
- 动态数据更新
-
- Kotlin 版本
- Java 版本
-
- 内存管理优化
-
- Kotlin 版本
- Java 版本
-
- 渲染优化
-
- Kotlin 版本
- Java 版本
-
- 调试与监控
-
- Kotlin 版本
- Java 版本
- 六、性能优化检查清单
-
- 1.必须实施的优化措施
-
- 性能陷阱提醒
- 七、Java VS Kotlin 总结
一、 基础配置对比
1.依赖添加
Gradle 配置,两者相同
gradle
dependencies {
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}
2.布局定义
XML,两者相同
xml
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/lineChart"
android:layout_width="match_parent"
android:layout_height="300dp" />
二、 折线图完整实现
Kotlin 版本
kotlin
class ChartActivity : AppCompatActivity() {
private lateinit var lineChart: LineChart
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chart)
lineChart = findViewById(R.id.lineChart)
setupLineChart()
setLineChartData()
}
private fun setupLineChart() {
// 基础配置
lineChart.apply {
setTouchEnabled(true)
setPinchZoom(true)
description.isEnabled = false
legend.isEnabled = false
}
// X轴配置
val xAxis = lineChart.xAxis
xAxis.apply {
position = XAxis.XAxisPosition.BOTTOM
setDrawGridLines(false)
granularity = 1f
textSize = 12f
textColor = Color.GRAY
// 自定义标签格式化
valueFormatter = object : ValueFormatter() {
override fun getAxisLabel(value: Float, axis: AxisBase?): String {
return "${value.toInt()}月"
}
}
}
// Y轴配置
lineChart.axisRight.isEnabled = false
val leftAxis = lineChart.axisLeft
leftAxis.apply {
setDrawGridLines(true)
axisMinimum = 0f
axisMaximum = 200f
textSize = 12f
textColor = Color.GRAY
}
}
private fun setLineChartData() {
// 创建模拟数据
val entries = ArrayList<Entry>().apply {
add(Entry(0f, 45f))
add(Entry(1f, 68f))
add(Entry(2f, 92f))
add(Entry(3f, 57f))
add(Entry(4f, 103f))
add(Entry(5f, 78f))
}
// 配置数据集
val dataSet = LineDataSet(entries, "月度数据").apply {
color = ContextCompat.getColor(this@ChartActivity, R.color.chart_line)
lineWidth = 2f
setDrawCircles(true)
circleRadius = 4f
circleHoleRadius = 2f
circleColors = listOf(ContextCompat.getColor(this@ChartActivity, R.color.chart_circle))
setDrawValues(false)
mode = LineDataSet.Mode.CUBIC_BEZIER // 曲线模式
}
// 设置数据并刷新
val lineData = LineData(dataSet)
lineChart.data = lineData
lineChart.invalidate()
// 添加动画
lineChart.animateY(1000)
}
}
Java 版本
java
public class ChartActivity extends AppCompatActivity {
private LineChart lineChart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chart);
lineChart = findViewById(R.id.lineChart);
setupLineChart();
setLineChartData();
}
private void setupLineChart() {
// 基础配置
lineChart.setTouchEnabled(true);
lineChart.setPinchZoom(true);
lineChart.getDescription().setEnabled(false);
lineChart.getLegend().setEnabled(false);
// X轴配置
XAxis xAxis = lineChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setGranularity(1f);
xAxis.setTextSize(12f);
xAxis.setTextColor(Color.GRAY);
// 自定义标签格式化
xAxis.setValueFormatter(new ValueFormatter() {
@Override
public String getAxisLabel(float value, AxisBase axis) {
return (int)value + "月";
}
});
// Y轴配置
lineChart.getAxisRight().setEnabled(false);
YAxis leftAxis = lineChart.getAxisLeft();
leftAxis.setDrawGridLines(true);
leftAxis.setAxisMinimum(0f);
leftAxis.setAxisMaximum(200f);
leftAxis.setTextSize(12f);
leftAxis.setTextColor(Color.GRAY);
}
private void setLineChartData() {
// 创建模拟数据
List<Entry> entries = new ArrayList<>();
entries.add(new Entry(0f, 45f));
entries.add(new Entry(1f, 68f));
entries.add(new Entry(2f, 92f));
entries.add(new Entry(3f, 57f));
entries.add(new Entry(4f, 103f));
entries.add(new Entry(5f, 78f));
// 配置数据集
LineDataSet dataSet = new LineDataSet(entries, "月度数据");
dataSet.setColor(ContextCompat.getColor(this, R.color.chart_line));
dataSet.setLineWidth(2f);
dataSet.setDrawCircles(true);
dataSet.setCircleRadius(4f);
dataSet.setCircleHoleRadius(2f);
dataSet.setCircleColor(ContextCompat.getColor(this, R.color.chart_circle));
dataSet.setDrawValues(false);
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
// 设置数据并刷新
LineData lineData = new LineData(dataSet);
lineChart.setData(lineData);
lineChart.invalidate();
// 添加动画
lineChart.animateY(1000);
}
}
三、 饼图完整实现
Kotlin 版本
kotlin
class PieChartActivity : AppCompatActivity() {
private lateinit var pieChart: PieChart
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pie_chart)
pieChart = findViewById(R.id.pieChart)
setupPieChart()
setPieChartData()
}
private fun setupPieChart() {
pieChart.apply {
setUsePercentValues(true) // 显示百分比
description.isEnabled = false
setDrawEntryLabels(false) // 不显示条目标签
setDrawCenterText(true)
centerText = "成绩分布"
setCenterTextSize(18f)
setCenterTextColor(Color.BLACK)
// 设置边距防止标签被裁剪
setExtraOffsets(20f, 5f, 20f, 5f)
}
// 图例配置
val legend = pieChart.legend
legend.apply {
verticalAlignment = Legend.LegendVerticalAlignment.CENTER
horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT
orientation = Legend.LegendOrientation.VERTICAL
setDrawInside(false)
textSize = 12f
}
// 启用旋转
pieChart.isRotationEnabled = true
}
private fun setPieChartData() {
val entries = listOf(
PieEntry(25f, "优秀"),
PieEntry(35f, "良好"),
PieEntry(20f, "中等"),
PieEntry(15f, "及格"),
PieEntry(5f, "不及格")
)
val dataSet = PieDataSet(entries, "").apply {
colors = getChartColors()
valueTextSize = 12f
valueTextColor = Color.WHITE
setDrawIcons(false)
sliceSpace = 2f // 扇形间距
selectionShift = 5f // 选中时突出距离
}
val pieData = PieData(dataSet).apply {
setValueFormatter(PercentFormatter(pieChart))
}
pieChart.data = pieData
pieChart.invalidate()
// 添加旋转动画
pieChart.animateY(1000, Easing.EaseInOutCubic)
}
private fun getChartColors(): List<Int> {
return listOf(
Color.parseColor("#FF6B6B"), // 红色
Color.parseColor("#4ECDC4"), // 青色
Color.parseColor("#45B7D1"), // 蓝色
Color.parseColor("#96CEB4"), // 绿色
Color.parseColor("#FFEAA7") // 黄色
)
}
}
Java 版本
java
public class PieChartActivity extends AppCompatActivity {
private PieChart pieChart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pie_chart);
pieChart = findViewById(R.id.pieChart);
setupPieChart();
setPieChartData();
}
private void setupPieChart() {
// 基础配置
pieChart.setUsePercentValues(true);
pieChart.getDescription().setEnabled(false);
pieChart.setDrawEntryLabels(false);
pieChart.setDrawCenterText(true);
pieChart.setCenterText("成绩分布");
pieChart.setCenterTextSize(18f);
pieChart.setCenterTextColor(Color.BLACK);
// 设置边距
pieChart.setExtraOffsets(20, 5, 20, 5);
// 图例配置
Legend legend = pieChart.getLegend();
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.CENTER);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setDrawInside(false);
legend.setTextSize(12f);
// 启用旋转
pieChart.setRotationEnabled(true);
}
private void setPieChartData() {
List<PieEntry> entries = new ArrayList<>();
entries.add(new PieEntry(25f, "优秀"));
entries.add(new PieEntry(35f, "良好"));
entries.add(new PieEntry(20f, "中等"));
entries.add(new PieEntry(15f, "及格"));
entries.add(new PieEntry(5f, "不及格"));
PieDataSet dataSet = new PieDataSet(entries, "");
dataSet.setColors(getChartColors());
dataSet.setValueTextSize(12f);
dataSet.setValueTextColor(Color.WHITE);
dataSet.setDrawIcons(false);
dataSet.setSliceSpace(2f);
dataSet.setSelectionShift(5f);
PieData pieData = new PieData(dataSet);
pieData.setValueFormatter(new PercentFormatter(pieChart));
pieChart.setData(pieData);
pieChart.invalidate();
// 添加动画
pieChart.animateY(1000, Easing.EaseInOutCubic);
}
private List<Integer> getChartColors() {
List<Integer> colors = new ArrayList<>();
colors.add(Color.parseColor("#FF6B6B"));
colors.add(Color.parseColor("#4ECDC4"));
colors.add(Color.parseColor("#45B7D1"));
colors.add(Color.parseColor("#96CEB4"));
colors.add(Color.parseColor("#FFEAA7"));
return colors;
}
}
四、 高级功能实现
1.自定义 MarkerView
Kotlin 版本
kotlin
class CustomMarkerView(context: Context, layoutResource: Int) : MarkerView(context, layoutResource) {
private val tvContent: TextView = findViewById(R.id.tvContent)
override fun refreshContent(e: Entry?, highlight: Highlight?) {
e?.let {
tvContent.text = "数值: ${it.y.toInt()}"
}
super.refreshContent(e, highlight)
}
override fun getOffset(): MPPointF {
// 调整位置:水平居中,显示在点上方
return MPPointF(-(width / 2).toFloat(), -height.toFloat())
}
}
// 使用 MarkerView
private fun setupMarkerView() {
val markerView = CustomMarkerView(this, R.layout.custom_marker_view)
markerView.chartView = lineChart
lineChart.marker = markerView
}
Java 版本
java
public class CustomMarkerView extends MarkerView {
private TextView tvContent;
public CustomMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
tvContent = findViewById(R.id.tvContent);
}
@Override
public void refreshContent(Entry e, Highlight highlight) {
tvContent.setText(String.format("数值: %.0f", e.getY()));
super.refreshContent(e, highlight);
}
@Override
public MPPointF getOffset() {
return new MPPointF(-(getWidth() / 2), -getHeight());
}
}
// 使用 MarkerView
private void setupMarkerView() {
CustomMarkerView markerView = new CustomMarkerView(this, R.layout.custom_marker_view);
markerView.setChartView(lineChart);
lineChart.setMarker(markerView);
}
2. 限制线配置
Kotlin 版本
kotlin
private fun setupLimitLine() {
val leftAxis = lineChart.axisLeft
// 创建平均值限制线
val averageLine = LimitLine(75f, "平均值").apply {
lineWidth = 2f
lineColor = Color.RED
textColor = Color.RED
textSize = 12f
enableDashedLine(10f, 10f, 0f) // 虚线
}
// 清除旧线并添加新线
leftAxis.removeAllLimitLines()
leftAxis.addLimitLine(averageLine)
// 确保坐标轴范围包含限制线
if (75f > leftAxis.axisMaximum) {
leftAxis.axisMaximum = 85f
}
}
Java 版本
java
private void setupLimitLine() {
YAxis leftAxis = lineChart.getAxisLeft();
// 创建平均值限制线
LimitLine averageLine = new LimitLine(75f, "平均值");
averageLine.setLineWidth(2f);
averageLine.setLineColor(Color.RED);
averageLine.setTextColor(Color.RED);
averageLine.setTextSize(12f);
averageLine.enableDashedLine(10f, 10f, 0f);
// 清除旧线并添加新线
leftAxis.removeAllLimitLines();
leftAxis.addLimitLine(averageLine);
// 确保坐标轴范围包含限制线
if (75f > leftAxis.getAxisMaximum()) {
leftAxis.setAxisMaximum(85f);
}
}
五、 性能优化实现
1.大数据量处理
Kotlin 版本
kotlin
private fun handleLargeDataSet() {
val rawData = generateLargeDataSet(10000) // 生成10000个数据点
// 数据抽样
val sampledData = if (rawData.size > 1000) {
sampleData(rawData, 10) // 每10个点取1个
} else {
rawData
}
val dataSet = LineDataSet(sampledData, "大数据集").apply {
setDrawCircles(false) // 不绘制圆圈提升性能
setDrawValues(false)
color = Color.BLUE
lineWidth = 1f
}
// 在后台线程设置数据
lifecycleScope.launch(Dispatchers.Default) {
val lineData = LineData(dataSet)
withContext(Dispatchers.Main) {
lineChart.data = lineData
lineChart.invalidate()
}
}
}
private fun sampleData(original: List<Entry>, interval: Int): List<Entry> {
return original.filterIndexed { index, _ -> index % interval == 0 }
}
Java 版本
java
private void handleLargeDataSet() {
List<Entry> rawData = generateLargeDataSet(10000);
// 数据抽样
List<Entry> sampledData;
if (rawData.size() > 1000) {
sampledData = sampleData(rawData, 10);
} else {
sampledData = rawData;
}
LineDataSet dataSet = new LineDataSet(sampledData, "大数据集");
dataSet.setDrawCircles(false);
dataSet.setDrawValues(false);
dataSet.setColor(Color.BLUE);
dataSet.setLineWidth(1f);
// 使用AsyncTask在后台处理
new AsyncTask<Void, Void, LineData>() {
@Override
protected LineData doInBackground(Void... voids) {
return new LineData(dataSet);
}
@Override
protected void onPostExecute(LineData lineData) {
lineChart.setData(lineData);
lineChart.invalidate();
}
}.execute();
}
private List<Entry> sampleData(List<Entry> original, int interval) {
List<Entry> sampled = new ArrayList<>();
for (int i = 0; i < original.size(); i++) {
if (i % interval == 0) {
sampled.add(original.get(i));
}
}
return sampled;
}
2. 动态数据更新
Kotlin 版本
kotlin
private fun updateChartData(newValue: Float) {
val data = lineChart.data
val dataSet = data.getDataSetByIndex(0) as LineDataSet
// 添加新数据点
val lastX = dataSet.getEntryForIndex(dataSet.entryCount - 1)?.x ?: 0f
dataSet.addEntry(Entry(lastX + 1, newValue))
// 限制数据点数量
if (dataSet.entryCount > 50) {
dataSet.removeFirst()
}
// 通知数据变化
data.notifyDataChanged()
lineChart.notifyDataSetChanged()
lineChart.invalidate()
// 自动滚动到最新位置
lineChart.moveViewToX(data.xMax)
}
Java 版本
java
private void updateChartData(float newValue) {
LineData data = lineChart.getData();
if (data != null) {
LineDataSet dataSet = (LineDataSet) data.getDataSetByIndex(0);
// 添加新数据点
float lastX = 0;
if (dataSet.getEntryCount() > 0) {
lastX = dataSet.getEntryForIndex(dataSet.getEntryCount() - 1).getX();
}
dataSet.addEntry(new Entry(lastX + 1, newValue));
// 限制数据点数量
if (dataSet.getEntryCount() > 50) {
dataSet.removeFirst();
}
// 通知数据变化
data.notifyDataChanged();
lineChart.notifyDataSetChanged();
lineChart.invalidate();
// 自动滚动到最新位置
lineChart.moveViewToX(data.getXMax());
}
}
3. 内存管理优化
Kotlin 版本
kotlin
class ChartMemoryManager : LifecycleObserver {
private var chart: LineChart? = null
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun cleanup() {
chart?.let {
it.data = null // 清除数据引用
it.clear() // 清理图表
it.setOnTouchListener(null) // 移除触摸监听
}
chart = null
}
fun setupChartWithMemoryManagement(chart: LineChart) {
this.chart = chart
// 禁用硬件加速(在某些设备上可减少内存使用)
chart.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
// 限制缓存大小
chart.setMaxVisibleValueCount(100)
}
// 分页加载大数据
fun loadDataInPages(chart: LineChart, allData: List<Entry>, pageSize: Int = 1000) {
val pages = allData.chunked(pageSize)
var currentPage = 0
fun loadNextPage() {
if (currentPage < pages.size) {
val pageData = pages[currentPage]
updateChartData(chart, pageData)
currentPage++
// 延迟加载下一页
chart.postDelayed({ loadNextPage() }, 100)
}
}
loadNextPage()
}
}
Java 版本
java
public class ChartMemoryManager implements LifecycleObserver {
private LineChart chart;
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void cleanup() {
if (chart != null) {
chart.setData(null);
chart.clear();
chart.setOnTouchListener(null);
}
chart = null;
}
public void setupChartWithMemoryManagement(LineChart chart) {
this.chart = chart;
chart.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
chart.setMaxVisibleValueCount(100);
}
}
4. 渲染优化
Kotlin 版本
kotlin
class ChartRenderOptimizer {
companion object {
// 预定义颜色避免重复创建
val CHART_COLORS = intArrayOf(
Color.parseColor("#FF6B6B"),
Color.parseColor("#4ECDC4"),
Color.parseColor("#45B7D1"),
Color.parseColor("#96CEB4")
)
}
fun optimizeRendering(chart: LineChart) {
chart.apply {
// 关闭不必要的绘制
setDrawMarkers(false)
setDrawBorders(false)
setDrawGridBackground(false)
// 优化坐标轴绘制
xAxis.setDrawGridLines(false)
axisLeft.setDrawGridLines(true)
axisLeft.setDrawZeroLine(false)
// 使用预定义颜色
data?.dataSets?.forEachIndexed { index, dataSet ->
val colorIndex = index % CHART_COLORS.size
when (dataSet) {
is LineDataSet -> dataSet.color = CHART_COLORS[colorIndex]
is BarDataSet -> dataSet.color = CHART_COLORS[colorIndex]
}
}
}
}
// 动态调整渲染质量
fun adjustRenderingQuality(chart: LineChart, isHighQuality: Boolean) {
chart.data?.dataSets?.forEach { dataSet ->
when (dataSet) {
is LineDataSet -> {
dataSet.setDrawCircles(isHighQuality)
dataSet.setDrawValues(isHighQuality)
dataSet.mode = if (isHighQuality)
LineDataSet.Mode.CUBIC_BEZIER
else
LineDataSet.Mode.LINEAR
}
}
}
}
}
Java 版本
java
public class ChartRenderOptimizer {
private static final int[] CHART_COLORS = {
Color.parseColor("#FF6B6B"),
Color.parseColor("#4ECDC4"),
Color.parseColor("#45B7D1"),
Color.parseColor("#96CEB4")
};
public void optimizeRendering(LineChart chart) {
chart.setDrawMarkers(false);
chart.setDrawBorders(false);
chart.setDrawGridBackground(false);
chart.getXAxis().setDrawGridLines(false);
chart.getAxisLeft().setDrawGridLines(true);
chart.getAxisLeft().setDrawZeroLine(false);
if (chart.getData() != null) {
for (int i = 0; i < chart.getData().getDataSetCount(); i++) {
IDataSet dataSet = chart.getData().getDataSetByIndex(i);
int colorIndex = i % CHART_COLORS.length;
if (dataSet instanceof LineDataSet) {
((LineDataSet) dataSet).setColor(CHART_COLORS[colorIndex]);
} else if (dataSet instanceof BarDataSet) {
((BarDataSet) dataSet).setColor(CHART_COLORS[colorIndex]);
}
}
}
}
}
5. 调试与监控
Kotlin 版本
kotlin
class ChartDebugHelper {
companion object {
const val DEBUG_TAG = "MPAndroidChart"
}
fun logChartPerformance(chart: LineChart, tag: String = DEBUG_TAG) {
val data = chart.data
if (data != null) {
val totalEntries = data.dataSets.sumBy { it.entryCount }
Log.d(tag, "图表数据统计:")
Log.d(tag, "数据集数量: ${data.dataSetCount}")
Log.d(tag, "总数据点: $totalEntries")
Log.d(tag, "X轴范围: ${data.xMin} - ${data.xMax}")
Log.d(tag, "Y轴范围: ${data.yMin} - ${data.yMax}")
}
}
// 内存使用监控
fun monitorMemoryUsage() {
val runtime = Runtime.getRuntime()
val usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024)
val maxMemory = runtime.maxMemory() / (1024 * 1024)
Log.d(DEBUG_TAG, "内存使用: ${usedMemory}MB / ${maxMemory}MB")
}
}
Java 版本
java
public class ChartDebugHelper {
private static final String DEBUG_TAG = "MPAndroidChart";
public static void logChartPerformance(LineChart chart) {
LineData data = chart.getData();
if (data != null) {
int totalEntries = 0;
for (int i = 0; i < data.getDataSetCount(); i++) {
totalEntries += data.getDataSetByIndex(i).getEntryCount();
}
Log.d(DEBUG_TAG, "图表数据统计:");
Log.d(DEBUG_TAG, "数据集数量: " + data.getDataSetCount());
Log.d(DEBUG_TAG, "总数据点: " + totalEntries);
Log.d(DEBUG_TAG, "X轴范围: " + data.getXMin() + " - " + data.getXMax());
Log.d(DEBUG_TAG, "Y轴范围: " + data.getYMin() + " - " + data.getYMax());
}
}
}
六、性能优化检查清单
1.必须实施的优化措施
1. 数据层面
- 大数据集进行抽样显示(>1000个点)
- 关闭不必要的绘制元素(圆圈、数值标签)
- 使用合适的数据结构存储数据
2. 渲染层面
- 禁用不需要的交互功能
- 简化坐标轴和图例
- 使用预定义颜色避免重复创建
3. 内存层面
- 在 onDestroy 中清理图表资源
- 限制可见数据点数量
- 避免在 RecyclerView 中过度使用图表
2. 性能陷阱提醒
- 避免在主线程处理大数据
- 不要频繁调用 invalidate()
- 谨慎使用动画效果
- 注意 RecyclerView 中的图表复用
- 及时清理不需要的监听器
七、Java VS Kotlin 总结
特性 | Kotlin 版本 | Java 版本 |
---|---|---|
空安全 | 使用 lateinit 和 ?. 操作符,更安全 |
需要手动进行 null 检查 |
集合操作 | 支持 apply 、let 、filterIndexed 等扩展函数 |
依赖传统循环和条件判断 |
代码简洁性 | 语法简洁,减少样板代码 | 相对冗长,需更多模板代码 |
异步处理 | 使用协程(lifecycleScope + Dispatchers ) |
使用 AsyncTask 或 Thread /Handler |
资源管理 | 自动管理生命周期与协程作用域 | 需手动管理线程与资源释放 |
结论 :两种语言在功能实现上完全一致,主要差异在于语法特性和现代编程范式的支持。Kotlin 版本通常更加简洁、安全、可读性强 ,而 Java 版本更传统、直观,适合已有 Java 基础的开发者。
📌 建议 :新项目推荐使用 Kotlin + 协程,兼顾性能、可维护性与开发效率。