关于flutter对象引用的理解
2020-11-24 本文已影响0人
HawkFlying
描述
在开发中,不可避免会将对象传递给其它对象使用,其它对象对传递来的对象的操作会引起原对象什么变化呢?
示例
示例有两个页面,一个页面展示原对象的变化,另一个页面展示对原对象引用操作对原对象的影响
原对象变化页:
import 'package:flutter/material.dart';
import 'test_model_cite_page.dart';
class ModelCitePage extends StatefulWidget {
const ModelCitePage();
@override
_ModelCitePageState createState() => _ModelCitePageState();
}
class _ModelCitePageState extends State<ModelCitePage> {
_ModelCitePageState();
CiteModel _testCiteModel;
@override
void initState() {
super.initState();
_testCiteModel = CiteModel(1);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('对象引用计数'),
),
body: Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'原对象:${_testCiteModel ?? ''}',
textAlign: TextAlign.center,
),
SizedBox(
height: 20,
),
RaisedButton(
child: Text("对象引用计数操作"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TestModelCitePage(_testCiteModel);
}),
);
},
),
],
),
),
);
}
@override
void deactivate() {
super.deactivate();
print('ModelCitePage deactivate ${_testCiteModel ?? 'null'}');
}
@override
void dispose() {
super.dispose();
}
}
对原对象引用操作页:
import 'package:flutter/material.dart';
class TestModelCitePage extends StatefulWidget {
final CiteModel _testCiteModel;
const TestModelCitePage(this._testCiteModel);
@override
_TestModelCitePageState createState() =>
_TestModelCitePageState(this._testCiteModel);
}
class _TestModelCitePageState extends State<TestModelCitePage> {
CiteModel _testCiteModel;
CiteModel _tmpTestCiteModel;
String operateText;
String showInfo;
String hintText;
_TestModelCitePageState(this._testCiteModel);
@override
void initState() {
super.initState();
print('test cite model page ${_testCiteModel ?? 'null'}');
_tmpTestCiteModel = _testCiteModel;
_updateView('_tmpTestCiteModel = _testCiteModel',
'外部传进来的_testCiteModel赋值给_tmpTestCiteModel');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('测试引用'),
),
body: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'操作:${operateText ?? ''}',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.green),
),
SizedBox(
height: 10,
),
Text(
showInfo ?? '',
textAlign: TextAlign.center,
),
SizedBox(
height: 10,
),
Text(
'提示:${hintText ?? ''}',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.redAccent),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("方法置空原对象"),
onPressed: () {
_nullModel(_testCiteModel);
_updateView(
'_nullModel(_testCiteModel)', '只是置空原对象引用,对原对象引用没影响');
},
),
RaisedButton(
child: Text("方法置空引用对象"),
onPressed: () {
_nullModel(_tmpTestCiteModel);
_updateView('_nullModel(_tmpTestCiteModel)',
'只是置空原对象引用,对原对象引用没影响');
},
),
],
),
RaisedButton(
child: Text("引用置为null"),
onPressed: () {
_testCiteModel = null; //不会影响_tmpTestCiteModel和传进来值
print('test cite model page ${_testCiteModel ?? 'null'}');
print(
'tmp test cite model page ${_tmpTestCiteModel ?? 'null'}');
_updateView(
'_testCiteModel = null', '不会影响_tmpTestCiteModel和传进来值');
},
),
SizedBox(
height: 20,
),
RaisedButton(
child: Text("赋值的引用置为null"),
onPressed: () {
_tmpTestCiteModel = null; //不会影响_testCiteModel和传进来值
print('test cite model page ${_testCiteModel ?? 'null'}');
_updateView(
'_tmpTestCiteModel = null', '不会影响_testCiteModel和传进来值');
},
),
SizedBox(
height: 20,
),
RaisedButton(
child: Text("引用重新赋值"),
onPressed: () {
_testCiteModel = CiteModel(2); //不会影响_tmpTestCiteModel和传进来值
print('test cite model page ${_testCiteModel ?? 'null'}');
print(
'tmp test cite model page ${_tmpTestCiteModel ?? 'null'}');
_updateView('_testCiteModel = CiteModel(2)',
'不会影响_tmpTestCiteModel和传进来值');
},
),
SizedBox(
height: 20,
),
RaisedButton(
child: Text("赋值的引用重新赋值"),
onPressed: () {
_tmpTestCiteModel = CiteModel(3); //不会影响_testCiteModel和传进来值
print('test cite model page ${_testCiteModel ?? 'null'}');
_updateView('_tmpTestCiteModel = CiteModel(3)',
'不会影响_testCiteModel和传进来值');
},
),
SizedBox(
height: 20,
),
RaisedButton(
child: Text("修改引用值"),
onPressed: () {
_testCiteModel?.count = 4; //影响_testCiteModel和传进来值
print('test cite model page ${_testCiteModel ?? 'null'}');
print(
'tmp test cite model page ${_tmpTestCiteModel ?? 'null'}');
_updateView(
'_testCiteModel?.count = 4', '影响_testCiteModel和传进来值');
},
),
SizedBox(
height: 20,
),
RaisedButton(
child: Text("修改赋值的引用值"),
onPressed: () {
_tmpTestCiteModel?.count = 5; //影响_tmpTestCiteModel和传进来值
print('test cite model page ${_testCiteModel ?? 'null'}');
_updateView('_tmpTestCiteModel.count = 5',
'影响_tmpTestCiteModel和传进来值');
},
),
],
),
),
),
);
}
@override
void deactivate() {
super.deactivate();
print('test cite page deactivate');
}
@override
void dispose() {
super.dispose();
print('test cite page dispose');
}
void _updateView(String operate, String hint) {
setState(() {
operateText = operate;
showInfo = 'test cite model: ${_testCiteModel ?? 'null'}\n' +
'tmp test cite model: ${_tmpTestCiteModel ?? 'null'}';
hintText = hint;
});
}
void _nullModel(CiteModel model) {
model = null;
}
}
class CiteModel {
int count;
CiteModel(this.count);
@override
String toString() {
return 'TestCiteModel count is $count';
}
}
操作:
1、将对象引用置为null
可以看到,普通方法和类的构造方法传参为对象时,传参只是产生对象的引用,将对象的引用置为null,并不会影响把原对象置null,这里个人觉得跟对象引用计数有关,将对象引用置null,只是将对象引用计数减1,只有引用计数为0时,对象才会被回收;
2、将对象引用重新实例化或赋值其它对象引用
可以看到,对象引用的重新实例化或赋值其它对象引用,对原对象没有影响;
3、对象引用里的成员变量值改变
可以看到,对象引用里的成员变量值改变,所有对象的引用都会变化
结论
个人理解,不对请多多指教
-
对象实例化时,实际是在内存空间创建属于自己的一片空间,类似创建了房子A;
A实例化.png -
将实例化的对象A赋值给A1对象或者再将A1对象赋值给A2对象,其实A1对象和A2对象都是这个实例化A对象的引用,也就是A1和A2都指向A的内存空间,类似A1和A2都有A房子的钥匙,可以进入A房子为所欲为;
对象引用.png - 对引用对象的成员变量改变时,所有对象的引用都会变化,类似A1进入A房子,换了墙的颜色,其他人进来A房子会看到变化;
-
将对象的引用置null或指向其它的对象,也就是让A1或A2不指向A的内存空间,对A所在的内存空间没有影响,类似于A1或A2将手里的钥匙换成其它房子的了,所以A1和A2以后再也和房子A无关了;
对象引用置null.png - 普通方法或类的构造方法的传参为对象时,传参实际是对对象的引用,将对象引用置null并不会影响原对象;