Flutter can't access data because it's potentially null - flutter

How can I define my function nullable? I get the following error on Flutter (InsertData is the function in repository.dart):
`lib/services/categoriesservices.dart:13:30: Error: Property
'InsertData' cannot be accessed on 'Repository?' because it is
potentially null.
'Repository' is from 'package:sqflite2/repositories/repository.dart'
('lib/repositories/repository.dart'). Try accessing using ?. instead.
return await _repository.InsertData.call(`
repository.dart seen below:
import 'package:sqflite/sqflite.dart';
import 'package:sqflite2/repositories/databaseconnection.dart';
class Repository {
DataBaseConnection? _dataBaseConnection;
Repository() {
//initialize database connection
_dataBaseConnection = DataBaseConnection();
}
static Database? _database;
Future<Database?> get database async {
if (_database != null) {
return _database;
}
_database = await _dataBaseConnection.setDatabase();
return database;
}
//create function inserting data to database
InsertData(table, data) async {
var connection = await database;
return await connection.insert(table, data);
}
}
The function is initialized as seen below:
import 'package:sqflite2/models/category.dart';
import 'package:sqflite2/repositories/repository.dart';
class CategoryService {
Repository? _repository;
CategoryService() {
_repository = Repository();
}
saveCategory(Categori category) async {
return await _repository.InsertData("categories", category.categoryMap());
}
}
What am I missing ? I thought I already initiliazed the Repository with (?)

You need to access the member functions, variables of your nullable object with ?
operator. Just declaring nullable will not satisfy the compiler. It can be null while accessing insertData function.
It performs a null check before accessing the function.
Try the below snippet with ? operator.
saveCategory(Categori category) async {
return await _repository?.InsertData("categories", category.categoryMap());
}
If you are certain that _repository object is not null while accessing the saveCategory(Categori category) function. You can use ! operator for force assurance that the object is not null (Not recommended).
return await _repository!.InsertData("categories", category.categoryMap());
You might also wanna look at late modifier
About nullable function
Return values
All functions return a value. If no return value is specified, the
statement return null; is implicitly appended to the function body.
Therefore, if you know the return type of your function, specify it. If the function may return null, use '?' after the return type.

Related

Flutter: I still get the error "Null check operator used on a null value" on the value I made Nullable

static Database? _db;
if (_db != null) {
return;
}
try {
String _path = await getDatabasesPath() + 'users.db';
_db =
await openDatabase(_path, version: _version, onCreate: (db, version) {
print("Database oluşturuldu");
});
} catch (e) {
print(e);
}
}
static Future<List<Map<String, dynamic>>> query() async {
print("query");
return await _db!.query(_tableName);
}
I get the error Null check operator used on a null value even though I made the _db value nullable.
Appreciate if someone can advise. Thank you in advance!
Nullable simply means that a variable can have a nullvalue. With the ! you assume that the variable is not null at this point and therefore you can call the method. But of course if you don't have a value assigned in your object now, then it will try to call the method on null value.
Initialize somewhere in the code your database object before you try to make a query.
You can return empty list or fetch again on null case, use ! only when you are certain the value is not null. It would be better to do a null check 1st.
static Future<List<Map<String, dynamic>>> query() async {
print("query");
final result = await _db?.query(_tableName);
if (result == null) {
print("got null db"); // you can reinitialize the db
return [];
} else {
return result;
}
}
static Database? _db;
//database was never initialized, null by default in this instance
static Future<List<Map<String, dynamic>>> query() async {
print("query");
//you attempt to get the value from a null object while casting it as non null
return await _db!.query(_tableName);
}
You have to initialize a null value before using the notation (!) on it else you're casting a null object as non-null. To avoid any errors, rewrite it as
return (await _db?.query(_tableName)) ?? [];
this will fail but no nullpointer exception will be thrown

Unhandled Exception: type 'Null' is not a subtype of type 'List<dynamic>' in type cast

Objective is to convert a String to List using map and return the value to a function call.
I am using SharedPreferences to save a list of object called where in I save the data at a point and get the data when it is to be put on view.
The below block is the function where the error is occurring.
void getData() async {
final prefs = await SharedPreferences.getInstance();
final String taskString = prefs.getString('task_data').toString();
List<Task> tasksData = Task.decode(taskString);
_tasks = tasksData;
notifyListeners();
}
decode() looks basically does the conversion.
static List<Task> decode(String tasks) {
return (jsonDecode(tasks) as List<dynamic>).map<Task>((task) {
return Task.fromJson(task);
}).toList();
It advises to check for null condition in type cast of decode(). But on performing the check, it gives the same error.
your response might be not a proper map so it cannot decode that data using the jsonDecode function so it returns Null, so you can use your function like this might be helpful for you :
static List<Task> decode(String tasks) {
var data = (jsonDecode(tasks) as List<dynamic>?);
if(data != null){
return (jsonDecode(tasks) as List<dynamic>?)!.map<Task>((task) {
return Task.fromJson(task);
}).toList();
} else {
return <Task>[];
}
}

Flutter - await/async on a List - why does this only work when not using declarations?

Still new to Flutter :(. Can anyone help...
I have a class that stores a bunch of project information. One part of this is a list of topics (for push notification), which it grabs from a JSON file.
I apply a getter for the list of topics, and when getting it it calls an async function which will return a List
Future<List<String>> _pntopics() async{
final _json = await http.get(Uri.parse(_topicsUrl));
if (_json.statusCode == 200) {
return (jsonDecode(_json.body));
}else {
return [""];
}
}
Future<List<String>> get topics => _pntopics();
In my main.dart file, it calls this value like so...
Future<List<String>> _topiclist = await projectvalues.topics;
The response is however empty, pressumably because it is a Future - so it is grabbing the empty value before it is filled.
But I can't remove the "Future" part from the async method, because asnc methods require a Future definition.
Then I decided to remove the declarations entirely:
_pntopics() async{
final _json = await http.get(Uri.parse(_topicsUrl));
if (_json.statusCode == 200) {
return (jsonDecode(_json.body));
}else {
return [""];
}
}
get topics => _pntopics();
and in main.dart, a general declaration...
var _topiclist = await projectvalues.topics;
...and this works!
So what declaration should I actually be using for this to work? I'm happy to not use declarations but we're always to declare everthing.
You should return back Future<List<String>> return types to the function and the getter but for _topicslist you must use var, final or List<String> declaration because:
(await Future<T>) == T
i.e.
var _topiclist = await projectvalues.topics; // The type of _topiclist is List<String>
final _topiclist = await projectvalues.topics; // The type of _topiclist is List<String>
UPDATE
Your code should be:
Future<List<String>> _pntopics() async{
final _json = await http.get(Uri.parse(_topicsUrl));
if (_json.statusCode == 200) {
return List<String>.from(jsonDecode(_json.body));
}else {
return <String>[""];
}
}
Doing this you force _pnptopics returns List<String> as jsonDecode returns List<dynamic>.
P.S. It is good practice do not use dynamic types where they can be changed to specified types.

Flutter SharedPreferences Null check operator used on a null value

I've made a class for shared preferences. The class is as follows
class StorageUtil {
static StorageUtil? _storageInstance;
static SharedPreferences? _preferences;
static Future<StorageUtil?> getInstance() async {
if (_storageInstance == null) {
_storageInstance = StorageUtil();
}
if (_preferences == null) {
_preferences = await SharedPreferences.getInstance();
}
return _storageInstance;
}
addStringtoSF(String key, String value) async {
print(' inside sharedPreferences file $key $value'); // Receives data here
await _preferences!.setString(key,
value); //Unhandled Exception: Null check operator used on a null value
}
When ever i try to store the values i'm getting a error 'Null check operator used on a null value'
This is how i'm passing down the values to the store function. I'm receiving the data inside the function. But cannot store the values inside it. What causes this?
String? userResponse = json.encode(authResponse);
print('This is userResponse type');
_storageUtil.addStringtoSF('userData', userResponse);
Try adding this WidgetsFlutterBinding.ensureInitialized();
in the very first line of you main() method in main.dart file if not present.
The problem over here is that
The class has a static function that is responsible for the initialization of variables and can be accessed without an object of class StorageUtil.
When the nonstatic function is called you need to create an object of StorageUtil class and then access that function due to which the static variables are not initialized which are initialized in the static function hence null.
From the snippet of code it seems you are willing to make a singleton class here is the correct code for it:
class StorageUtil {
static StorageUtil storageInstance = StorageUtil._instance();
static SharedPreferences? _preferences;
StorageUtil._instance(){
getPreferences();
}
void getPreferences()async{
_preferences = await SharedPreferences.getInstance();
}
addStringtoSF(String key, String value) async {
print(' inside sharedPreferences file $key $value'); // Receives data here
await _preferences!.setString(key,
value);
}
}
Where ever you want the preference to be used just call:
final StorageUtil storage = StorageUtil.storageInstance;
storage.AnyNonStaticFunctionName()// call for methods in the StorageUtil Class
this is the one and only object that will exist throughout the application.
Or
if you don't want to change your class then just add this in all the nonstatic functions at the top which uses _preferences
And also add this null check
if (_preferences == null) {
_preferences = await SharedPreferences.getInstance();
}
because you may be having multiple instances of the StorageUtil making the _preferences variable null each time.
Add this line also under your print line, before calling _preferences!.
if (_preferences == null) {
_preferences = await SharedPreferences.getInstance();
}

Non-nullable instance field '_db' must be initialized. (Documentation)

I'm try do something here but getting an error
NotesDBWorker.dart
class NotesDBWorker {
NotesDBWorker._();
static final NotesDBWorker db = NotesDBWorker._();
Database _db;
Future get database async {
// ignore: unnecessary_null_comparison
if (_db == null) {
_db = await init();
}
return _db;
}
}
If you want your variable to have a null state, you should declare it as nullable by adding a ? after the name of the type. Using late will result in a runtime LateInitializationError.
class NotesDBWorker {
NotesDBWorker._();
static final NotesDBWorker db = NotesDBWorker._();
Database? _db;
Future get database async {
if (_db == null) {
_db = await init();
}
return _db;
}
}
You should generally also not be suppressing analyzer warnings. They are there for a reason.