Dart: A Future (NULL) was instantiated to NON-NULL in a method, and then mysteriously reverted back to NULL

huangapple go评论60阅读模式
英文:

Dart: A Future (NULL) was instantiated to NON-NULL in a method, and then mysteriously reverted back to NULL

问题

以下是您要翻译的代码部分:

In the test shown (selected for demonstration of the issue),  main()  instantiates Class ReadWrite() and then calls method readwrite().   Method readwrite() calls getmap() to create img.Image maptrack and then saves it via saveimage() method successfully.  Next, Method readwrite() calls THE SAME saveimage() METHOD and fails on CastError (Null check operator used on a null value)
 
How can an object,  start as NULL, convert to NON-NULL in a method and then suddenly appear as NULL in a subsequent method?   Its as if the method created its own version,  and did not change the class object.   If the object is global, I get the same result.

// maptrack is NULL in calling program but is NOT NULL
// in called program

import 'package:image/image.dart' as img;
import 'dart:io'; //for file read/write
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:path/path.dart' as path;
import 'dart:typed_data'; // for Uint8List types
import 'timestamp.dart'; //  prints elapsed seconds + message - code not shown here

main() {
    ReadWrite r = new ReadWrite();
    Time t = new Time();

    String mapid = '041a10.png';
    Pixel p = Pixel(3380, 2211);

    t.timestamp('#0 hello world from main()');
    r.readwrite(t, p, mapid).then((_) {
        print("Hello There -  Finished Normally");
    });
}

class ReadWrite {
    img.Image? maptrack;

    Future<void> readwrite(t, p, mapid) async {
         await getmap(t, mapid);
        maptrack != null
            ? print("#6 maptrack NOT NULL")
            : print('#6 maptrack IS NULL'); //NULL
        await saveimage(t, 'maptrack.png', maptrack!); // CRASH!!
            //_CastError (Null check operator used on a null value)
    }

    Future<bool> getmap(Time t, String mapid) async {
        t.timestamp("#3 start getmap() ");
        Directory appDir = await path_provider.getApplicationDocumentsDirectory();
        String thepath = path.join(appDir.path, mapid); // 031e01.jpg
        img.Image? maptrack = await img.decodePngFile(thepath);
        t.timestamp("#4 getmap done. loaded maptrack ");
        maptrack != null
            ? print("#5 maptrack NOT NULL") //NOT NULL
            : print('#5 maptrack IS NULL');
        await saveimage(t, 'maptrack.png', maptrack!);
        return (true); // not used - enables an await call in readwrite()
    }

    /* save marked map as 031e01.png*/
    Future<bool> saveimage(Time t, String mapid, img.Image map) async {
        Directory appDir = await path_provider.getApplicationDocumentsDirectory();
        String pngPath = path.join(appDir.path, mapid); // 031e01.png
        Uint8List markedmap = img.encodePng(map); //convert image to list
        await File(pngPath).writeAsBytes(markedmap);
        t.timestamp('#8a $mapid SAVED');
        return (true); // not used - enables an await call in readwrite()
    }
}

class Pixel {
    int x;
    int y;
    Pixel(this.x, this.y); //constructor

    /* https://coflutter.com/dart-how-to-print-an-object/  */
    @override
    String toString() {
        return 'Pixel: {x: ${x}, y: ${y} }';
    }
}

代码在崩溃之前输出以下内容:

flutter: #0 hello world from main() = 0 seconds
flutter: #3 start getmap()  = 0 seconds
flutter: #4 getmap done. loaded maptrack  = 8 seconds
flutter: #5 maptrack NOT NULL
flutter: #8a maptrack.png SAVED = 24 seconds
flutter: #6 maptrack IS NULL
英文:

In the test shown (selected for demonstration of the issue), main() instantiates Class ReadWrite() and then calls method readwrite(). Method readwrite() calls getmap() to create img.Image maptrack and then saves it via saveimage() method successfully. Next, Method readwrite() calls THE SAME saveimage() METHOD and fails on CastError (Null check operator used on a null value)

How can an object, start as NULL, convert to NON-NULL in a method and then suddenly appear as NULL in a subsequent method? Its as if the method created its own version, and did not change the class object. If the object is global, I get the same result.

// maptrack is NULL in calling program but is NOT NULL
// in called program
import &#39;package:image/image.dart&#39; as img;
import &#39;dart:io&#39;; //for file read/write
import &#39;package:path_provider/path_provider.dart&#39; as path_provider;
import &#39;package:path/path.dart&#39; as path;
import &#39;dart:typed_data&#39;; // for Uint8List types
import &#39;timestamp.dart&#39;; //  prints elapsed seconds + message - code not shown here
main() {
ReadWrite r = new ReadWrite();
Time t = new Time();
String mapid = &#39;041a10.png&#39;;
Pixel p = Pixel(3380, 2211);
t.timestamp(&#39;#0 hello world from main()&#39;);
r.readwrite(t, p, mapid).then((_) {
print(&quot;Hello There -  Finished Normally&quot;);
});
}
class ReadWrite {
img.Image? maptrack;
Future&lt;void&gt; readwrite(t, p, mapid) async {
await getmap(t, mapid);
maptrack != null
? print(&quot;#6 maptrack NOT NULL&quot;)
: print(&#39;#6 maptrack IS NULL&#39;); //NULL
await saveimage(t, &#39;maptrack.png&#39;, maptrack!); // CRASH!!
//_CastError (Null check operator used on a null value)
}
Future&lt;bool&gt; getmap(Time t, String mapid) async {
t.timestamp(&quot;#3 start getmap() &quot;);
Directory appDir = await path_provider.getApplicationDocumentsDirectory();
String thepath = path.join(appDir.path, mapid); // 031e01.jpg
img.Image? maptrack = await img.decodePngFile(thepath);
t.timestamp(&quot;#4 getmap done. loaded maptrack &quot;);
maptrack != null
? print(&quot;#5 maptrack NOT NULL&quot;) //NOT NULL
: print(&#39;#5 maptrack IS NULL&#39;);
await saveimage(t, &#39;maptrack.png&#39;, maptrack!);
return (true); // not used - enables an await call in readwrite()
}
/* save marked map as 031e01.png*/
Future&lt;bool&gt; saveimage(Time t, String mapid, img.Image map) async {
Directory appDir = await path_provider.getApplicationDocumentsDirectory();
String pngPath = path.join(appDir.path, mapid); // 031e01.png
Uint8List markedmap = img.encodePng(map); //convert image to list
await File(pngPath).writeAsBytes(markedmap);
t.timestamp(&#39;#8a $mapid SAVED&#39;);
return (true); // not used - enables an await call in readwrite()
}
}
class Pixel {
int x;
int y;
Pixel(this.x, this.y); //constructor
/* https://coflutter.com/dart-how-to-print-an-object/  */
@override
String toString() {
return &#39;Pixel: {x: ${x}, y: ${y} }&#39;;
}
}`
```
The code outputs the following before it crashes.
flutter: #0 hello world from main() = 0 seconds
flutter: #3 start getmap()  = 0 seconds
flutter: #4 getmap done. loaded maptrack  = 8 seconds
flutter: #5 maptrack NOT NULL
flutter: #8a maptrack.png SAVED = 24 seconds
flutter: #6 maptrack IS NULL
```
```
</details>
# 答案1
**得分**: 1
Sure, here's the translated code part:
在你的 `getMap` 方法中,你声明了一个新的局部变量 `maptrack`,而不是赋值给类/实例变量 `maptrack`。
```dart
Future<bool> getmap(Time t, String mapid) async {
t.timestamp("#3 start getmap()");
Directory appDir = await path_provider.getApplicationDocumentsDirectory();
String thepath = path.join(appDir.path, mapid); // 031e01.jpg
img.Image? maptrack = await img.decodePngFile(thepath); // 在这里声明了一个新变量
t.timestamp("#4 getmap done. loaded maptrack");
maptrack != null
? print("#5 maptrack NOT NULL") //NOT NULL
: print('#5 maptrack IS NULL');
await saveimage(t, 'maptrack.png', maptrack!);
return (true); // not used - enables an await call in readwrite()
}
```
移除 `img.Image?` 类型声明,改为引用实例变量。
```dart
Future<bool> getmap(Time t, String mapid) async {
t.timestamp("#3 start getmap()");
Directory appDir = await path_provider.getApplicationDocumentsDirectory();
String thepath = path.join(appDir.path, mapid); // 031e01.jpg
maptrack = await img.decodePngFile(thepath); // 移除 img.Image?
t.timestamp("#4 getmap done. loaded maptrack");
maptrack != null
? print("#5 maptrack NOT NULL") //NOT NULL
: print('#5 maptrack IS NULL');
await saveimage(t, 'maptrack.png', maptrack!);
return (true); // not used - enables an await call in readwrite()
}
```
<details>
<summary>英文:</summary>
Within your `getMap` method you are declaring a new local variable `maptrack` instead of assigning to the class/instance variable `maptrack`.
```dart
Future&lt;bool&gt; getmap(Time t, String mapid) async {
t.timestamp(&quot;#3 start getmap() &quot;);
Directory appDir = await path_provider.getApplicationDocumentsDirectory();
String thepath = path.join(appDir.path, mapid); // 031e01.jpg
img.Image? maptrack = await img.decodePngFile(thepath); // declaring a new variable here
t.timestamp(&quot;#4 getmap done. loaded maptrack &quot;);
maptrack != null
? print(&quot;#5 maptrack NOT NULL&quot;) //NOT NULL
: print(&#39;#5 maptrack IS NULL&#39;);
await saveimage(t, &#39;maptrack.png&#39;, maptrack!);
return (true); // not used - enables an await call in readwrite()
}
```
Remove the type `img.Image?` before `maptrack` to refer instead to the instance variable.
```dart
Future&lt;bool&gt; getmap(Time t, String mapid) async {
t.timestamp(&quot;#3 start getmap() &quot;);
Directory appDir = await path_provider.getApplicationDocumentsDirectory();
String thepath = path.join(appDir.path, mapid); // 031e01.jpg
maptrack = await img.decodePngFile(thepath); // removed img.Image?
t.timestamp(&quot;#4 getmap done. loaded maptrack &quot;);
maptrack != null
? print(&quot;#5 maptrack NOT NULL&quot;) //NOT NULL
: print(&#39;#5 maptrack IS NULL&#39;);
await saveimage(t, &#39;maptrack.png&#39;, maptrack!);
return (true); // not used - enables an await call in readwrite()
}
```
</details>

huangapple
  • 本文由 发表于 2023年5月14日 02:15:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76244258.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定