Flutter第7天--字体图标,2021年Android开发进阶课程

 var line1_4 = Row(
  children: <Widget>[
    Image.asset("images/icon_90.png", width: 20, height: 20),
    Expanded(
      child: pd(Text("张风捷特烈"), l: 5),
    ),
    Text(
      "Flutter/Dart",
      style: infoStyle,
    )
  ],
);

var center_right = Column(
  mainAxisSize: MainAxisSize.min,
  children: <Widget>[
    Text(
      "Flutter第4天--基础控件(下)+Flex布局详解",
      style: littelStyle,
      maxLines: 2,
    ),
    pd(
        Text(
          "1.2:优雅地查看:图片的适应模式--BoxFit1.3:优雅地查看:颜色混合模式--colorBlendMode",
          style: infoStyle,
          maxLines: 2,
          overflow: TextOverflow.ellipsis,
        ),
        t: 5),
  ],
);

//中间的信息
var center4 = Row(
children: [
Expanded(child: pda(center_right, 5)),
Image.asset(
“images/wy_300x200.jpg”,
width: 80,
height: 80,
fit: BoxFit.fitHeight,
)
],
);

var end4 = Row(
  children: <Widget>[
    Icon(
      Icons.grade,
      color: Colors.green,
      size: 20,
    ),
    Text(
      "1000W",
      style: infoStyle,
    ),
    pd(Icon(Icons.tag_faces, color: Colors.lightBlueAccent, size: 20),
        l: 15, r: 5),
    Text("2000W", style: infoStyle),
  ],
);

var item4 = Column(
  children: <Widget>[line1_4, Expanded(child: center4), end4],
);

var aCard = Card(
    child: Container(
        height: 160,
        color: Colors.white,
        padding: EdgeInsets.all(10),
        child: item4));

return aCard;

}
}


* * *

##### 4.动态数据获取:

> 昨天已经把http获取数据的内容将过了,并且把服务端的数据解析了

今天就是使用这些数据,来填充静态界面,`api接口介绍`和`NoteBean`[昨天已完成]( )

> 封装一个获取数据的方法:简单说下用法:

`style是类型:Android是A ;SpringBoot是SB ; React 是Re ; 笔记是 Note`  
`offset和num 联合使用可以达到分页效果, 比如offset=24,num=12,就是一页12条数据的第3页`

import ‘dart:convert’;

import ‘package:http/http.dart’ as client;
import ‘package:toly/pager/day7/bean.dart’;

const BASE_URL = ‘http://192.168.43.60:8089’;//api接口的域名自己改一下
const API = ‘/api/android/note/’;

Future<List> get({style = ‘’, offset = 0, num = 1}) async {
var dataLi = [];
var url = BASE_URL + API + style + “/” + “ o f f s e t " + " / " + " offset" + "/" + " offset"+"/"+"num”;
try {
final response = await client.get(url);
if (response.statusCode == 200) {
var result = ResultBean.fromJson(json.decode(response.body));
List data = result.data;
print(NoteBean.fromJson(data[0]).type);
for (int i = 0; i < data.length; i++) {
dataLi.add(NoteBean.fromJson(data[i]));
}
return dataLi;
}
} catch (e) {
print(e);
}
}


* * *

##### 5.用一个数据来进行填充测试:

> `主页面:android_stack.dart`,`initState`的时候获取数据,并更新状态

![动态获取数据填充.png](https://user-gold-cdn.xitu.io/2018/12/22/167d5170974f36fc?imageView2/0/w/1280/h/960/ignore-error/1)

//定义一个成员变量
List _notes = [];

@override
void initState() {
super.initState();

get(num: 1).then((beanLi) {
_notes = beanLi;
setState(() {});
});
}


> `列表界面:home_list.dart`:接收主界面传来的\_notes,并渲染数据

class HomeListPage extends StatefulWidget {
List _notes;
HomeListPage(List notes) {
_notes = notes;
}
@override
_HomeListPageState createState() => _HomeListPageState();
}

class _HomeListPageState extends State {
@override
Widget build(BuildContext context) {
var notes = widget._notes;

return ListView.builder(
  itemCount: notes.length,
  itemBuilder: (BuildContext context, int index) {
    return renderItem(notes[index]);
  },
);

}
//渲染条目
renderItem(NoteBean note) {
var line1_4 = Row(
children: [
Image.asset(“images/icon_90.png”, width: 20, height: 20),
Expanded( child: pd(Text(“张风捷特烈”), l: 5),),
Text( note.type,style: infoStyle,)
],
);
var center_right = Column(
mainAxisSize: MainAxisSize.min,
children: [Text(note.name,style: littelStyle,maxLines: 2,),
pd(Text( note.info, style: infoStyle, maxLines: 2,
overflow: TextOverflow.ellipsis, ), t: 5),
],
);

//中间的信息
var center4 = Row(
children: [
Expanded(child: pda(center_right, 5)),
Image.network( note.imgUrl,
width: 80, height: 80, fit: BoxFit.fitHeight )
],
);

var end4 = Row(
  children: <Widget>[
    Icon( Icons.grade, color: Colors.green, size: 20, ),
    Text( "1000W", style: infoStyle,),
    pd(Icon(Icons.tag_faces, color: Colors.lightBlueAccent, size: 20),
        l: 15, r: 5),
    Text("2000W", style: infoStyle),
  ],
);

var item4 = Column(
  children: <Widget>[line1_4, Expanded(child: center4), end4],
);

var aCard = Card(
    child: Container(  height: 160,color: Colors.white,
        padding: EdgeInsets.all(10), child: item4));
return aCard;

}
}


* * *

> `现在万事俱备,东风也到了,num小小动一下:num=30`

| \-- | \-- |
| --- | --- |
| ![](https://user-gold-cdn.xitu.io/2018/12/22/167d51709ffc6a9c?imageView2/0/w/1280/h/960/ignore-error/1) | ![](https://user-gold-cdn.xitu.io/2018/12/22/167d5170a05707f4?imageView2/0/w/1280/h/960/ignore-error/1) |

> 也许你感觉还未开始,但确实已经结束了...

* * *

##### 6.底部导航栏的切换:(下面两个图一样的,为了撑场面...)

> 刚才是数据没有分类型,现在点击底部导航,按范围进行展示

`get(style: "area/A", num: 30)//这样就是展示又有安卓类的文章`

| \- | \- |
| --- | --- |
| ![](https://user-gold-cdn.xitu.io/2018/12/22/167d5170524fc96d?imageslim) | ![](https://user-gold-cdn.xitu.io/2018/12/22/167d5170524fc96d?imageslim) |

> `android_stack.dart`添加成员变量

这里我默认加载完,做分页的话,再添加个\_count的成员变量就行了

String style = “area/A”;

//页面打开,默认加载安卓页
@override
void initState() {
super.initState();
get(style: style, num: 1000).then((beanLi) {
_notes = beanLi;
setState(() {});
});
}

//底部栏点击监听—动态改变范围
void _onTapBNB(int position) {
switch (position) {
case 0:
style = “area/A”;
break;
case 1:
style = “area/SB”;
break;
case 2:
style = “area/Re”;
break;
case 3:
style = “area/Note”;
break;
case 4:
style = “area/A”;
break;
}
_curIndex = position;
get(style: style, num: 1000).then((beanLi) {
_notes = beanLi;
setState(() {});
});
}


* * *

##### 7.底部栏和搜索功能

> 底部栏用法详情在[第四篇]( )

| \-- | \-- |
| --- | --- |
| ![底部栏.gif](https://user-gold-cdn.xitu.io/2018/12/22/167d5170a78c318b?imageslim) | ![搜索功能.gif](https://user-gold-cdn.xitu.io/2018/12/22/167d5170d2b02a9b?imageslim) |

* * *

> 底部栏:这里把事件写在里面了,你也可以抽成方法

或者有些控件太长,你也可以抽出来做变量

var searchSheet = BottomSheet(
onClosing: () {},
builder: (context) => (Card(
color: Color.fromARGB(255, 214, 242, 251),
child: Wrap(
children: [
Center(child: pdhv(TextField(
onChanged: (v) {style = “name/” + v;}), h: 60)),
Center(child: pdhv( GestureDetector(child:
Image.asset(“images/icon_90.png”,width: 50,height: 50 ),
onTap: () {
get(style: style, num: 1000).then((beanLi) {
_notes = beanLi;
setState(() {});
});
},
),
v: 10)),
],
))));

//点击按钮弹出:
var scContext; //先声明一下Scaffold的context
var scaffold = Scaffold(
appBar: AppBar(
title: Text(“张风捷特烈”),
),
body: Builder(builder: (context) {
scContext = context;
return HomeListPage(_notes);
}),
floatingActionButton: FloatingActionButton(
onPressed: () {
Scaffold.of(scContext).showBottomSheet(searchSheet.builder);
},
//下面不用修改,略…


> Ok,小案例就这样

* * *

#### 三、Android代码交互

##### 1.最简单的无参无返回函数调用:`两对应`

> 不得不说:前六天不能弹吐司真是不好受,原生交互肯定先拿他开刀

![toast](https://user-gold-cdn.xitu.io/2018/12/22/167d5170df8cc666?imageslim)

* * *

##### 1.1:Android代码

public class MainActivity extends FlutterActivity {
private static final String CHANNEL = “www.toly1994.com/test.名字随意起”;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);

    new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
            new MethodChannel.MethodCallHandler() {
                @Override
                public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                    if (methodCall.method.equals("showToast")) {
                        showToast("Hello Flutter,I am in Android");
                    } else {
                        result.notImplemented();
                    }
                }
            }
    );
}
/**
 * 显示吐司
 *
 * @param msg 信息
 */
public void showToast(String msg) {
    Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
    toast.show();
}

}

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

const platform = const MethodChannel("www.toly1994.com/test.名字随意起");

var toastTest = Center(
  child: RaisedButton(
    onPressed: () {
      platform.invokeMethod("showToast");
    },
    child: new Text("点击弹吐司"),
  ),
); 
```

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tRvfzX7u-1630575188188)(https://user-gold-cdn.xitu.io/2018/12/22/167d5170e66818b6?imageView2/0/w/1280/h/960/ignore-error/1)]

* * *

##### 2.Flutter中传参,调用Android含参方法:`三对应`

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GNsBJKrv-1630575188190)(https://user-gold-cdn.xitu.io/2018/12/22/167d5170f0db9d31?imageslim)]

* * *

###### 2.1:Android代码

```
public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "www.toly1994.com/test.名字随意起";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);

        new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
                new MethodChannel.MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                        if (methodCall.method.equals("showToast")) {
                            //解析参数
                            String msg = methodCall.argument("msg");
                            showToast(msg);
                        } else {
                            result.notImplemented();
                        }
                    }
                }
        );
    }

    /**
     * 显示吐司
     *
     * @param msg 信息
     */
    public void showToast(String msg) {
        Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
        toast.show();
    }
} 
```

* * *

###### 2.2:Flutter代码:

```
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

const platform = const MethodChannel("www.toly1994.com/test.名字随意起");

var toastTest = Center(
  child: RaisedButton(
    onPressed: () {
      platform.invokeMethod("showToast",{"msg":"Flutter大爷我赏你一口吐司"});
    },
    child: new Text("点击弹吐司"),
  ),
); 
```

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WDOOICUq-1630575188191)(https://user-gold-cdn.xitu.io/2018/12/22/167d5171179fcfc7?imageView2/0/w/1280/h/960/ignore-error/1)]

* * *

##### 2.3:加返回值的方法调用:

> 举什么例子,我想了一会,就来个MD5码吧

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2JDBmWLS-1630575188192)(https://user-gold-cdn.xitu.io/2018/12/22/167d5170f261c2c6?imageslim)]

```
//Activity添加判断分支
if (methodCall.method.equals("getMD5")) {
    String arg = methodCall.argument("arg");
    String md5 = getMD5(arg);
    result.success(md5);
}

    /**
     * 获取一个字符串的Md5值
     *
     * @param content 内容
     * @return Md5值
     */
    public String getMD5(String content) {
        content = content + "芝麻开门";
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(content.getBytes());
            return getHashString(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String getHashString(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString();
    } 
```

###### 2.2:Flutter代码:

```
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

const platform = const MethodChannel("www.toly1994.com/test.名字随意起");

var toastTest = Center(
  child: RaisedButton(
    onPressed: () {

      var result= platform.invokeMethod("getMD5",{"arg":"https://www.jianshu.com/p/9bac0072d1a0"});
      result.then((str){
        platform.invokeMethod("showToast",{"msg":str});
      });

    },
    child: new Text("点击弹吐司"),
  ),
); 
```

> 基本上也就这三种情况

* * *

#### \[彩蛋\]--以前Mark的一个小点:Card的shape

> 有人说学习的时候一个问题会牵扯到很多其他的问题,问题一多就无从下手

我只说一个字:"栈":来最后一波学习看源码的方法了,走起

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltKKPt8D-1630575188194)(https://user-gold-cdn.xitu.io/2018/12/22/167d5171179a8413?imageView2/0/w/1280/h/960/ignore-error/1)]

* * *

##### 1.shape是什么:形状

> 现在的问题栈

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gyNgUIQR-1630575188195)(https://user-gold-cdn.xitu.io/2018/12/22/167d517115e44d44?imageView2/0/w/1280/h/960/ignore-error/1)]

> 可见默认圆角是4的RoundedRectangleBorder

```
---->[shape属性]----
/// The default shape is a [RoundedRectangleBorder] with a circular corner
/// radius of 4.0.
final ShapeBorder shape;

---->[RoundedRectangleBorder]----
 const RoundedRectangleBorder({
    this.side = BorderSide.none,
    this.borderRadius = BorderRadius.zero,
    
//可见有两个属性:BorderSide和BorderRadius

---->[BorderSide]----
class BorderSide {
  /// Creates the side of a border.
  ///
  /// By default, the border is 1.0 logical pixels wide and solid black.
  const BorderSide({
    this.color = const Color(0xFF000000),
    this.width = 1.0,
    this.style = BorderStyle.solid,

---->[BorderRadius]----
class BorderRadius extends BorderRadiusGeometry {
  /// Creates a border radius where all radii are [radius].
  const BorderRadius.all(Radius radius) : this.only(
    topLeft: radius,
    topRight: radius,
    bottomLeft: radius,
    bottomRight: radius,
  );

  /// Creates a border radius where all radii are [Radius.circular(radius)].
  BorderRadius.circular(double radius) : this.all(
    Radius.circular(radius),
  );
  
---->[Radius]------
class Radius {
  /// Constructs a circular radius. [x] and [y] will have the same radius value.
  const Radius.circular(double radius) : this.elliptical(radius, radius);

  /// Constructs an elliptical radius with the given radii.
  const Radius.elliptical(this.x, this.y);

  /// The radius value on the horizontal axis.
  final double x;

  /// The radius value on the vertical axis.
  final double y; 
```

> 一个shape牵扯出这么多类,有人可能就`栈溢出`了,还是使用默认的吧,等一下,且听我分析  
> 当Radius入问题栈之后,看一下也就是两个值,就出栈了,BorderRadius跟着也出栈了

BorderSide三个字段,看一下,出栈了,现在栈顶是`RoundedRectangleBorder`你还不会吗?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vbIPJRZu-1630575188195)(https://user-gold-cdn.xitu.io/2018/12/22/167d51712855008f?imageView2/0/w/1280/h/960/ignore-error/1)]

##### 2\. RoundedRectangleBorder改变圆角大小+边线

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFFbtS8p-1630575188196)(https://user-gold-cdn.xitu.io/2018/12/22/167d517126b1edb1?imageView2/0/w/1280/h/960/ignore-error/1)]

```
var card_shape = Card(
//    shape: CircleBorder(side: BorderSide(width: 1)),
    shape: RoundedRectangleBorder(
      side:BorderSide(color: Color(0xffD516F5),width: 5) ,
        borderRadius: BorderRadius.all(Radius.circular(20))),
    clipBehavior: Clip.antiAlias,
    child: Container(
      width: 100,
      height: 100,
      color: Color(0xffCDECF6),
      child: Center(child:Text(
        "捷",
        style: TextStyle(color: Colors.black,fontSize: 40),
      ) ,),
    )); 
```

> 那弹栈过后问题跑哪里?  
> 我想应该是`临时知识库`吧,你解决的问题中获取的知识,经验会累积

可能长久不用知识库里的知识会漏掉,但印象有的,下一次再入栈,解决起来会更快  
在的知识库里扎根的知识,那当你遇到时,就不是问题,直接弹栈,这样想学习是不是也挺好玩的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFEP76D7-1630575188197)(https://user-gold-cdn.xitu.io/2018/12/22/167d517126a8b549?imageView2/0/w/1280/h/960/ignore-error/1)]

> 大神级的Coder知识库丰富,问题都不是问题,也许偶尔入栈一两个,但栈很深(感觉挺浪费哈)

新手就是栈比较浅,问题多,所以容易`StackOver`,所以修炼你容忍问题的能力(栈深)很有必要  
像我这样不深不浅的刚刚好,会碰到问题,也能一点点解决,一点一点踏上`封神之路`  
但所有的大神也都是从新手这样过来的,解决问题的能力也不是与生俱来,祝你慢慢弹栈,收获多多。

* * *

##### 3.接下来看`ShapeBorder`在栈顶,我们去瞅瞅

> BorderSide现在已经化敌为友,CircleBorder岂不是秒出栈,并且俘获`CircleBorder`一枚

而且BorderSide强化+1,知识就是这样积累的,难道还有别的方法吗?除非记忆拷贝...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YFLQAa5i-1630575188197)(https://user-gold-cdn.xitu.io/2018/12/22/167d51713ab9272b?imageView2/0/w/1280/h/960/ignore-error/1)]

> 转一转当CD背景感觉挺不错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CG9Gy99V-1630575188198)(https://user-gold-cdn.xitu.io/2018/12/22/167d51714791220f?imageView2/0/w/1280/h/960/ignore-error/1)]

```
var card_shape = Card(
    shape: CircleBorder(side: BorderSide(width: 15,color: Color(0xffF9DFA7))),
    clipBehavior: Clip.antiAlias,
    child: Container(
      width: 100,
      height: 100,
      color: Color(0xffCDECF6),
      child: Center(child:Text(
        "捷",
        style: TextStyle(color: Colors.black,fontSize: 40),
      ) ,),
    )); 
```

* * *

##### 4.前方高能,非战斗人员带好零食

> 其实觉得shape好玩,是在粗略看源码时,看到了canvas,才mark的

自定义ShapeBorder走起:画具在手,天下我有

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MlU9ww1-1630575188199)(https://user-gold-cdn.xitu.io/2018/12/22/167d5171490840b8?imageView2/0/w/1280/h/960/ignore-error/1)]

```
var card_shape = Card(
    shape: StarBorder(),
//    shape: CircleBorder(side: BorderSide(width: 15,color: Color(0xffF9DFA7))),
//    shape: RoundedRectangleBorder(
//      side:BorderSide(color: Color(0xffD516F5),width: 5) ,
//        borderRadius: BorderRadius.all(Radius.circular(20))),
    clipBehavior: Clip.hardEdge,
    child: Container(
      width: 100,
      height: 100,
      color: Color(0xffCDECF6),
      child: Center(
        child: Text(
          "捷",
          style: TextStyle(color: Colors.black, fontSize: 40),
        ),
      ),
    ));

class StarBorder extends ShapeBorder {
  @override
  // TODO: implement dimensions
  EdgeInsetsGeometry get dimensions => null;

  @override
  Path getInnerPath(Rect rect, {TextDirection textDirection}) {
    // TODO: implement getInnerPath
    return null;
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection textDirection}) {
    print(rect.right);
    return regularPolygonPath(10, 50,x: rect.height/2,y: rect.width/2);
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {
    canvas.translate(50, 50);
//    canvas.drawPath(nStarPath(5, 40, 20), new Paint());
  }

  @override
  ShapeBorder scale(double t) {
    // TODO: implement scale
    return null;
  }
} 
```

##### 路径封装(稍微优化了一下)

```
/**
 * n角星路径
 *
 * @param num 几角星
 * @param R   外接圆半径
 * @param r   内接圆半径
 * @return n角星路径
 */
Path nStarPath(int num, double R, double r, {x = 0, y = 0}) {
  Path path = new Path();
  double perDeg = 360 / num; //尖角的度数
  double degA = perDeg / 2 / 2;
  double degB = 360 / (num - 1) / 2 - degA / 2 + degA;

  path.moveTo(cos(_rad(degA)) * R+x, (-sin(_rad(degA)) * R+y));
  for (int i = 0; i < num; i++) {
    path.lineTo(
        cos(_rad(degA + perDeg * i)) * R+x, -sin(_rad(degA + perDeg * i)) * R+y);
    path.lineTo(
        cos(_rad(degB + perDeg * i)) * r+x, -sin(_rad(degB + perDeg * i)) * r+y);
  }
  path.close();
  return path;
}

/**
 * 画正n角星的路径:
 *
 * @param num 角数
 * @param R   外接圆半径
 * @return 画正n角星的路径
 */
Path regularStarPath(int num, double R,{x = 0, y = 0}) {
  double degA, degB;
  if (num % 2 == 1) {
    //奇数和偶数角区别对待
    degA = 360 / num / 2 / 2;
    degB = 180 - degA - 360 / num / 2;
  } else {
    degA = 360 / num / 2;
    degB = 180 - degA - 360 / num / 2;
  }
  double r = R * sin(_rad(degA)) / sin(_rad(degB));
  return nStarPath(num, R, r,x: x,y:y);
}

/**
 * 画正n边形的路径
 *
 * @param num 边数
 * @param R   外接圆半径
 * @return 画正n边形的路径
 */
Path regularPolygonPath(int num, double R,{x = 0, y = 0}) {
  double r = R * cos(_rad(360 / num / 2)); //!!一点解决
  return nStarPath(num, R, r,x: x,y:y);
}

/**
 * 角度制化为弧度制
 *
 * @param deg 角度
 * @return 弧度
 */
double _rad(double deg) {
  return deg * pi / 180;
} 
```

> `师傅领进门,修行在个人`,我已经把功力传给你了,能否修成正果,就看各自造化。

`事了拂衣去,深藏功与名`,Ok,Flutter七日游,完`捷`散花,自认为没有烂尾,耶!

* * *

#### 后记:捷文规范

##### 1.本文成长记录及勘误表

| [项目源码]( ) | 日期 | 备注 |
| --- | --- | --- |
| [V0.1-github]( ) | 2018-12-22 | [Flutter第7天--字体图标+综合小案例+Android代码交互]( ) |

##### 2.更多关于我

| 笔名 | QQ | 微信 | 爱好 |
| --- | --- | --- | --- |
| 张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
| [我的github]( ) | [我的简书]( ) | [我的掘金]( ) | [个人网站]( ) |

##### 3.声明

> 1----本文由张风捷特烈原创,转载请注明

2----欢迎广大编程爱好者共同交流  
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正  
4----看到这里,我在此感谢你的喜欢与支持

* * *

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2CxibTnP-1630575188199)(https://user-gold-cdn.xitu.io/2018/12/19/167c65f3be8ce58e?imageView2/0/w/1280/h/960/ignore-error/1)]

  
#### 《设计思想解读开源框架》

![](https://img-blog.csdnimg.cn/img_convert/386d03bfb1f2fdc8745c62823476ac88.png)

**第一章、 热修复设计**

* **第一节、 AOT/JIT & dexopt 与 dex2oat**

* **第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题**

* **第三节、热修复设计之热修复原理**

* **第四节、Tinker 的集成与使用(自动补丁包生成)**

  ![](https://img-blog.csdnimg.cn/img_convert/080e6a5970c879ff7c3317a5bdef7cbf.png)

  **第二章、 插件化框架设计**

* **第一节、 Class 文件与 Dex 文件的结构解读**

* **第二节、 Android 资源加载机制详解**

* **第三节、 四大组件调用原理**

* **第四节、 so 文件加载机制**

* **第五节、 Android 系统服务实现原理**

  ![](https://img-blog.csdnimg.cn/img_convert/debd50a0c69746632abbe4a1af661102.png)

  **第三章、 组件化框架设计**

* **第一节、阿里巴巴开源路由框——ARouter 原理分析**

* **第二节、APT 编译时期自动生成代码&动态类加载**

* **第三节、 Java SPI 机制**

* **第四节、 AOP&IOC**

* **第五节、 手写组件化架构**

  ![](https://img-blog.csdnimg.cn/img_convert/3a726310770647be47511721ba77839c.png)

  **第四章、图片加载框架**

* **第一节、图片加载框架选型**

* **第二节、Glide 原理分析**

* **第三节、手写图片加载框架实战**

  ![](https://img-blog.csdnimg.cn/img_convert/f1bc476328e0c0f551667dc419d021c1.png)

  **第五章、网络访问框架设计**

* **第一节、网络通信必备基础**

* **第二节、OkHttp 源码解读**

* **第三节、Retrofit 源码解析**

  ![](https://img-blog.csdnimg.cn/img_convert/26030454f66869238e7f5d1dd3229a68.png)

  **第六章、 RXJava 响应式编程框架设计**

* **第一节、链式调用**

* **第二节、 扩展的观察者模式**

* **第三节、事件变换设计**

* **第四节、Scheduler 线程控制**

  ![](https://img-blog.csdnimg.cn/img_convert/b32e494c781b9f879742ef99212c7e5d.png)

  **第七章、 IOC 架构设计**

* **第一节、 依赖注入与控制反转**

* **第二节、ButterKnife 原理上篇、中篇、下篇**

* **第三节、Dagger 架构设计核心解密**

  ![](https://img-blog.csdnimg.cn/img_convert/ea1f44a2227cdb7c962cbb74bcdea9d2.png)

  **第八章、 Android 架构组件 Jetpack**

* **第一节、 LiveData 原理**

* **第二节、 Navigation 如何解决 tabLayout 问题**

* **第三节、 ViewModel 如何感知 View 生命周期及内核原理**

* **第四节、 Room 架构方式方法**

* **第五节、 dataBinding 为什么能够支持 MVVM**

* **第六节、 WorkManager 内核揭秘**

* **第七节、 Lifecycles 生命周期**

  ![](https://img-blog.csdnimg.cn/img_convert/369554a55aa1fe32646766a0061ef526.png)
  **本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**
  ![](https://img-blog.csdnimg.cn/img_convert/37b655e9552fa22ad81ee245260ae251.png)

**[CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》](https://codechina.csdn.net/m0_60958482/android_p7)**
网络通信必备基础**

* **第二节、OkHttp 源码解读**

* **第三节、Retrofit 源码解析**

  [外链图片转存中...(img-g51FV4xx-1630575188203)]

  **第六章、 RXJava 响应式编程框架设计**

* **第一节、链式调用**

* **第二节、 扩展的观察者模式**

* **第三节、事件变换设计**

* **第四节、Scheduler 线程控制**

  [外链图片转存中...(img-WxnVEffh-1630575188203)]

  **第七章、 IOC 架构设计**

* **第一节、 依赖注入与控制反转**

* **第二节、ButterKnife 原理上篇、中篇、下篇**

* **第三节、Dagger 架构设计核心解密**

  [外链图片转存中...(img-XepbonMc-1630575188204)]

  **第八章、 Android 架构组件 Jetpack**

* **第一节、 LiveData 原理**

* **第二节、 Navigation 如何解决 tabLayout 问题**

* **第三节、 ViewModel 如何感知 View 生命周期及内核原理**

* **第四节、 Room 架构方式方法**

* **第五节、 dataBinding 为什么能够支持 MVVM**

* **第六节、 WorkManager 内核揭秘**

* **第七节、 Lifecycles 生命周期**

  [外链图片转存中...(img-fm6ldd3j-1630575188205)]
  **本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**
  [外链图片转存中...(img-U3GFuV02-1630575188206)]

**[CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》](https://codechina.csdn.net/m0_60958482/android_p7)**
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值