关于flutter对象引用的理解

描述

在开发中,不可避免会将对象传递给其它对象使用,其它对象对传递来的对象的操作会引起原对象什么变化呢?

示例

示例有两个页面,一个页面展示原对象的变化,另一个页面展示对原对象引用操作对原对象的影响
原对象变化页:

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

效果.gif

可以看到,普通方法和类的构造方法传参为对象时,传参只是产生对象的引用,将对象的引用置为null,并不会影响把原对象置null,这里个人觉得跟对象引用计数有关,将对象引用置null,只是将对象引用计数减1,只有引用计数为0时,对象才会被回收;

2、将对象引用重新实例化或赋值其它对象引用

效果.gif

可以看到,对象引用的重新实例化或赋值其它对象引用,对原对象没有影响;

3、对象引用里的成员变量值改变

效果.gif

可以看到,对象引用里的成员变量值改变,所有对象的引用都会变化

结论

个人理解,不对请多多指教

  • 对象实例化时,实际是在内存空间创建属于自己的一片空间,类似创建了房子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并不会影响原对象;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容