Is there a way to execute a method which is under a Button Click? - flutter

I use Flutter. I have a method inside a button click event which executes.
I want to execute that method as soon as the dart screen opens just once. I cannot put the method inside the widget build as it would execute everytime the state is refreshed. Is there a way to execute button click event without the user actualy clicking on the button?
EDIT : I’m aware that I can use a boolean or some variable and set it to false after executing once. I was just looking for a way around that.

Just call it in the initState method, like this:
#override
void initState() {
yourMethodOnClick();
super.initState();
}
This is in case you are using it StatefulWidget
Either you use StatelessWidget You should call the method in the contractor, like this:
YourClass extends StatelessWidget{
YourClass() {
yourMethodOnClick();
}
}

Related

Open dialog box in Flutter Stateless widget using ChangeNotifierProvider

I have a Stateless flutter widget which shows a list of TODOs. The list is shown using a ChangeNotifierProvider (of TodoList object, which contains a list of todos). Now when I load the page, I want to show a dialog box asking user to enter a new TODO if and only if the existing todos is empty. Inside the builder of the ChangeNotifierProvider, i tried below logic
if (todoList.todos.length == 0) {
_showDialog(context);
return Column...;
} else {
return ListBuilder...;
}
But its showing 2 dialog box (probably due to the build method executing twice). I have to pass context to dialog box because I'm updating the todoList inside it, which should trigger a rebuild.
How do I handle this scenario. I've tried using flag (_isDialogOpen) but its not still working?
make the widget Stateful in order to use it's lifecycle methods, you can use then initState() for showing the dialog when the page widgets are inserted in the widget tree, but you will need to use an addPostFrameCallback() to schedule showing it 1 frame after the initState's code gets executed:
First, import:
import package:flutter/scheduler.dart.
Then use this:
#override
void initState() {
// ...
SchedulerBinding.addPostFrameCallback((_) => _showDialog(context),);
}

How do I call a function within my main page from another file?

I have the following problem:
My Stateful Widget "HomePage" has an Function:
void refresh() {
//not important for now
}
But, my whole save and load functions are located in an extra file (save_load.dart)
It's not a class or whatever, just pure functions that I can call from every other file.
void loadList(String key) {
//not important as well
//The following line is what I basically want to achieve
HomePage.refresh();
}
My Problem now is: I want to call the function refresh() after/within the loadList() function. Do you have an idea on how I can achieve this?
Thank you so much!
Summary
The easiest way to achieve what you're looking to do is to use a GlobalKey<HomePageState> to reference the currentState of your HomePage widget and then call the refresh method.
Solution
First: Create your Global Key
Create your global key and pass it into your HomePage when you create it.
final GlobalKey<HomePageState> homeKey = GlobalKey<HomePageState>();
...
// In one of your build methods where you're creating your `HomePage` widget.
HomePage(key: homeKey, ...)
Second: Get The Current State
Next, you'll need to get access to the current state of your HomePage widget.
final homePageState = homeKey.currentState;
Last: Call Refresh
Finally, you'll want to call the refresh method using the state class you retrieved from the GlobalKey.
// This is how you access it safely
homePageState?.refresh(); // will only call refresh if the homePageState is not null
// OR
homePageState!.refresh(); // will throw if homePageState is null

How to attend best practice for not using UI code in the Controller with GetX flutter when I need to show a Dialog if my task complete.?

For a simple Email login with OTP code I have a structure as follows.
View
await _signUpCntrl.signUp(email, password);
Controller
_showOtpDialog(email);
_showOtpDialog func
return Get.dialog(
AlertDialog(
So the thing is _showOtpDialog function is inside a controller file. ie. /Controllers/controller_file.dart
I want do something like a blocListener, call the _showOtpDialog from a screen(view) file on signup success. (also relocate the _showOtpDialog to a view file)
Using GetX I have to use one of the builders either obs or getbuilder. Which is I think not a good approach to show a dialog box.
On internet it says Workers are the alternative to BlocListener. However Workers function resides on Controller file and with that the dialog is still being called on the controller file.
As OTP dialog will have its own state and a controller I wanted to put it inside a /view/viewfile.dart
How do I obtain this?
I tried using StateMixin but when I call Get.dialog() it throw an error.
visitChildElements() called during build
Unlike BLoC there's no BlocListener or BlocConsumer in GetX.
Instead GetX has RxWorkers. You can store your response object in a Rx variable:
class SomeController extends GetxController{
final response= Rxn<SomeResponse>();
Future<void> someMethod()async{
response.value = await someApiCall();
}
}
And then right before the return of your widget's build method:
class SomeWidget extends StatelessWidget{
final controller = Get.put(SomeController());
#override
Widget build(BuildContext context){
ever(controller.response, (SomeResponse res){
if(res.success){
return Get.dialog(SuccessDialog()); //Or snackbar, or navigate to another page
}
....
});
return UI();
}
First thing, you will need to enhance the quality of your question by making things more clearly. Add the code block and the number list, highlight those and making emphasize texts are bold. Use the code block instead of quote.
Seconds things, Depends on the state management you are using, we will have different approaches:
Bloc (As you already added to the question tag). By using this state management, you controller ( business logic handler) will act like the view model in the MVVM architecture. In terms of that, You will need to emit a state (e.g: Sent success event). Afterward, the UI will listen to the changes and update it value according to the event you have emitted. See this Bloc example
GetX (As your code and question pointed out): GetX will acts a little bit different. you have multiple ways to implement this:
Using callbacks (passed at the start when calling the send otp function)
Declare a general dialog for your application ( this is the most used when it comes to realization) and calling show Dialog from Bloc
Using Rx. You will define a Reactive Variable for e.g final success = RxBool(true). Then the view will listen and update whenever the success changes.
controller.dart
class MyController extends GetxController {
final success = RxBool(false);
void sendOtp() async {
final result = await repository.sendOTP();
success.update((val) => {true});
}
}
view.dart
class MyUI extends GetView<MyController> {
#override
Widget build(BuildContext context) {
ever(controller.success, (bool success) {
// This will update things whenever success is updated
if (success) {
Get.dialog(AlertDialog());
}
});
return Container();
}
}

Why is my Widget not updated after preferences are set? [duplicate]

The PreferenceActivity seems like a really easy helper class to manage the preferences of an app.
I'd like to also use that same class from the widget.
On the first instance of a widget I want the PreferenceActivity to come up. This was very easy to do from the configuration activity but here is the glitch...
I can't tell when the preference edit is completed!
All examples of widget preferences I see on the net use a manually built preference screen rather than the PreferenceActivity helper class and then listen for the 'save' button being clicked.
How can I do that with the PreferenceActivity since that activity doesn't have a save button. You just use the 'back' button to commit your preferences changes.
Thanks!
I have been trying to do the same thing and I think I've cracked it. I handle the onBackPressed() event in the PreferenceActivity and perform a widget update from there using sendBroadcast().
In PreferenceActivity:
#Override
public void onBackPressed() {
Intent intent=getIntent();
Bundle extras=intent.getExtras();
int widgetId=extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
// this is the intent broadcast/returned to the widget
Intent updateIntent = new Intent(this, WidgetProvider.class);
updateIntent.setAction("PreferencesUpdated");
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
sendBroadcast(updateIntent);
}
In your WidgetProvider:
#Override
public void onReceive(Context context, Intent intent) {
if ("PreferencesUpdated".equals(action)) {
// update your widget here
// my widget supports multiple instances so I needed to uniquely identify them like this
RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget);
int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
updateWidgetView(context, remoteView, appWidgetId);
}
}
NOTE: In 1.5 onBackPressed isn't support so comment out the #Override for onBackPressed and add this code
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(LOG_TAG, "onKeyDown() "+ keyCode);
if (keyCode==KeyEvent.KEYCODE_BACK && Integer.parseInt(Build.VERSION.SDK)<5) {
onBackPressed();
}
}
I should add that I'm new to Android development so I may be doing this entirely wrong. All I can say it is works for me :)
Let me know how you get on.
You should be able to tell when the Preference edits are complete by implementing a SharedPreferences.OnShredPreferenceChangeListener. Using this, you could update only when certain keys are changed, or unconditionally when any are changed. Remember to register it in your PreferenceActivity onCreate and unregister it in the onDestroy.
In this case, you can do something similar to Android: How do I force the update of all widgets of a particular kind within the listener to cause all of your widgets to update based on a SharedPreference change.
It's an old question, so this may not be relevant anymore.

Using PreferencesActivity from a widget?

The PreferenceActivity seems like a really easy helper class to manage the preferences of an app.
I'd like to also use that same class from the widget.
On the first instance of a widget I want the PreferenceActivity to come up. This was very easy to do from the configuration activity but here is the glitch...
I can't tell when the preference edit is completed!
All examples of widget preferences I see on the net use a manually built preference screen rather than the PreferenceActivity helper class and then listen for the 'save' button being clicked.
How can I do that with the PreferenceActivity since that activity doesn't have a save button. You just use the 'back' button to commit your preferences changes.
Thanks!
I have been trying to do the same thing and I think I've cracked it. I handle the onBackPressed() event in the PreferenceActivity and perform a widget update from there using sendBroadcast().
In PreferenceActivity:
#Override
public void onBackPressed() {
Intent intent=getIntent();
Bundle extras=intent.getExtras();
int widgetId=extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
// this is the intent broadcast/returned to the widget
Intent updateIntent = new Intent(this, WidgetProvider.class);
updateIntent.setAction("PreferencesUpdated");
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
sendBroadcast(updateIntent);
}
In your WidgetProvider:
#Override
public void onReceive(Context context, Intent intent) {
if ("PreferencesUpdated".equals(action)) {
// update your widget here
// my widget supports multiple instances so I needed to uniquely identify them like this
RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget);
int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
updateWidgetView(context, remoteView, appWidgetId);
}
}
NOTE: In 1.5 onBackPressed isn't support so comment out the #Override for onBackPressed and add this code
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(LOG_TAG, "onKeyDown() "+ keyCode);
if (keyCode==KeyEvent.KEYCODE_BACK && Integer.parseInt(Build.VERSION.SDK)<5) {
onBackPressed();
}
}
I should add that I'm new to Android development so I may be doing this entirely wrong. All I can say it is works for me :)
Let me know how you get on.
You should be able to tell when the Preference edits are complete by implementing a SharedPreferences.OnShredPreferenceChangeListener. Using this, you could update only when certain keys are changed, or unconditionally when any are changed. Remember to register it in your PreferenceActivity onCreate and unregister it in the onDestroy.
In this case, you can do something similar to Android: How do I force the update of all widgets of a particular kind within the listener to cause all of your widgets to update based on a SharedPreference change.
It's an old question, so this may not be relevant anymore.