flutter hot reload other pages - flutter

I am beginner of flutter.
Text (printA ())
and
PrintA () {print ("A"); retuen "A";}
are executed on page A of Flutter, and "A" is displayed in the console after hot reloading. Then navigate to page B and print "B" to the console as well. At this time, if I hot reload, not only "B" but also "A" will be displayed on the console. If I repeat the screen navigation, the number of A and B displayed on the console will continue to increase with one hot reload. What is the reason for this?
class PageA extends StatelessWidget {
const WordPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: MyDrawer(),
appBar: AppBar(
title: Text("PageA"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(printA()),
],
),
),
);
}
}
printA() {
print("A");
return "A";
}
Also, if I just make a screen navigate in the emulator without hot reloading, only "A" on page A and only "B" on page B will be displayed on the console as usual. and I use m1 mac.

A widget that manages a set of child widgets with a stack discipline.
Many apps have a navigator near the top of their widget hierarchy in
order to display their logical history using an Overlay with the most
recently visited pages visually on top of the older pages. Using this
pattern lets the navigator visually transition from one page to
another by moving the widgets around in the overlay. Similarly, the
navigator can be used to show a dialog by positioning the dialog
widget above the current page.
This is from the doc https://api.flutter.dev/flutter/widgets/Navigator-class.html your new page 'B' is just above the previous page 'A' which was never destroyed. And hot reload is causing the build method of page 'A' run again and you get 'A' printed.

Related

Flutter pull to refresh on lower part of screen

I have a app that looks like the picture above.
When i swipe right or left, page switches along with the pageview content. but NOT the image part, it stays still.
When i implement pull to refresh on this case, the gap opens above image part showing progress indicator and refreshes.
I want the refresher crack open between image and content part, how do i achieve this?
thank you so much for reply in advance, you are the hero.
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
const Expanded(
child: SizedBox(height: 200), //The 'Image Part'
),
SmartRefresher(
child: PageView.builder(itemBuilder: (context, state) => Column(
children:[SizedBox(height:200),PageContent()], itemCount: 3),//The 'Content Part'
)
],
));
}
}
Example code added above, this represents what i would like to implement, I want the refresher only accessible inside PageContent()
but i could not because it contains Column inside
seems like an issue with your stack.
if you want the image part to also follow the swipe it has to be within the pageview.builder.
For the refresh, under pageview.builder wrap the content part in the pull-to-refresh widget but not the image.
This is possibly caused by the Stack widget
Change your Stack to a Column
Wrap your SmartRefresher with and Expanded widget for your ListviewBuilder to take the remaining space in vertical axis. You will have an unbounded high error otherwise
Set the shrinkwrap of your ListviewBuilder to true for it to build your list elements on demand
That's it! ☑️

onPressed in D-PAD not working in Flutter running in Android TV after focus TextField

I have developed a small app for Android Tv, everything works great, but if there is a TextField on the screen, the focus control becomes quite unstable, especially onPressed/onTap, etc. events stop working (when using D-Pad, in simulator o real AndroidTV device)
I've been trying to fix this for several days. I've tried using FocusNode, change the focus manually in onSubmitted, etc.
In the main I use Shortcuts with LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
And I have followed several examples.
The application uses other forms, some with dinamically ListView (with buttons and checks in the rows) and none of them gives focus problem.
I just need to know why in a simple screen, with two textfields and a button, after entering a textfield and selecting the button, onPressed stops working. If no textfield has been selected and the button gets focus first, then no problem.
Very important to clarify that the button receives the focus and is highlighted, but onPressed does not work. I have tried different types of buttons and InkWell. The problem is not in the focus I think, but in performing the action of the button
Even using a FocusNode.listener, I can check that the button gets the focus, but I onPressed is not working. Same result assigning a focusNode to each element
Sometimes with a single textfield it seems to work but it's random
I leave a simple example, using Flutter 3, but same result in previous versions
Thanks in advance
import 'package:flutter/material.dart';
class TVForm extends StatefulWidget {
const TVForm({Key? key}) : super(key: key);
#override
State<TVForm> createState() => _TVFormState();
}
class _TVFormState extends State<TVForm> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(50.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: const [
Expanded(child: TextField()),
SizedBox(width: 20),
Expanded(child: TextField()),
],
),
ElevatedButton(
onPressed: () {
debugPrint("pressed!");
},
child: const Text("ok"))
],
),
),
);
}
}
If you want to test this in a AndroidTV emulator or real device, it's necessary to add
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
into intent-filter of manifest, and also add
<uses-feature android:name="android.software.leanback"
android:required="false" />
More info about configure Flutter app for Android tv here
UPDATE: If instead of a button there are two buttons in a row, then after returning from the textfield, the first button gets the focus but it doesn't work on Pressed, but the second one does!, and when returning to the first one it works again. That is, the following widget that captures the focus after the textfield does not work onpressed, but the following one does.

bloc eventController is closed unexpected

i´ve an app that should support responsive design.
In the mobile view I am using the scaffold drawer for the main menu:
return Scaffold(
appBar: AppBar(
title: title,
),
drawer: MainMenuDrawer(),
body: body,
);
In the desktop view the menu should always be visible, so i don´t use the drawer propery. Instead of that i´ve added the same menu as widget into a row:
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true ,
title: title
),
body: Row(
children: [
MainMenuDrawer(),
Expanded(child: body),
],
),
);
The menu has a logout button which sends an event to my authentication bloc and pops all pages from the navigation stack, to get to the first page (login page).
authenticationBloc.add(AuthenticationEvent.loggedOut());
while (Navigator.canPop(context)) {
Navigator.pop(context);
}
The authentication bloc is as singleton:
#singleton
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState>
As long as i am using the mobile view, I can logout from everywhere and it´s works as expected.
But when I switch to the desktop view the logout button doesn´t work anymore.
In the debug mode, I can see, that the eventController of the authBloc is already closed, so no event is added:
void add(Event event) {
if (_eventController.isClosed) return; <- isClosed is true
Does anyone know why this happened in the desktop view?
i´ve found the problen In the onTap method of my listitem.
To close the drawer i´ve called the Navigator.pop(context).
But this will cause the previous page to be closed when the menu is used as drawer.

Is that possible to cache widget to resue?

I am using getbody() method to get app body and the getbody() return a Widget If i change the variable ct count the the getbody() will return different widget and each widget is stroied in Listqueue<MyPage()> if i set variable ct value 1 it return widget from my list at position 1 and if i set variable ct 2 then it will return corresponding widget .
But the problem is in each widget i am doing an api call but when i reuse that widget it is again calling the API call and why this is calling after first time nd how to stop calling api when i am reusing the widget
ListQueue<Page> page1, page2, page3, page4;
_AppFramePageState() {
page1 = ListQueue();
page1.add(Page(widget: AppHomePage(), title: "Home Page"));
page2 = ListQueue();
page2.add(
Page(widget: TemplesListing(), title: "Temple listing"));
page3 = ListQueue();
page3.add(Page(widget: AppCommunities(), title: "Communities"));
page4 = ListQueue();
page4.add(Page(widget: AppVideos(), title: "Media"));
}
If user click on cart button from toolbar then i will add more value to page1 list and if user click on back button then i will remove last item from page1 list
Widget getBody() {
//This code is solved my 50% issue but renaming 50% is there. How to solve this issue?
return IndexedStack(
index: _selectedIndex,
children: <Widget>[
page1.last.widget,
page2.last.widget,
page3.last.widget,
page4.last.widget
],);<br>
//This is the code i used first time
switch (_selectedIndex) {
case 0:
return page1.last.widget;
case 1:
return page2.last.widget;
case 2:
return page3.last.widget;
case 3:
return page4.last.widget;
}
}
class Page{
Widget widget;
String title;
Page({this.title,this.widget});
}
Note: All widgets are StatefulWidget
In general, it's not possible to reuse the widgets.
You can manually reuse the cache widget by comparing old and new state of the widgets. Which is very lengthy and i don't think you should follow it.
There are many State management architecture patterns like Provider, BLOC, MOBX etc. to manage your app in a great way. They are used to improve your app performance and decrease widget re-renders, manage data flow across the whole app etc.
One more thing you can do to make your Stateful widgets more impactive by using the const keyword whenever possible.
like for following widget ,
Column(
children: <Widget>[
// Widget 1
Center(child: Text(dynamic_value),),
// Widget 2
Container(
child: const Center(
child: const Padding(
padding: const EdgeInsets.all(10),
child: Text("Hello"),
),
),
),
],
)
In above example for Widget 1, you can't use "const keyword" as it depends on "dynamic_value".
While for Widget 2, you can use the "const keyword" which will be useful if your build method gets called again then "Center", "Padding" & "Text" widgets will be not called again as they are declared as constant widgets.

Why is Flutter disposing my widget state object in a tabbed interface?

I have a tabbed Flutter interfaces using DefaultTabController with 3 pages, each a stateful widget. I seem to be able to switch between the first two tabs just fine, but when I tab to the 3rd page the state object for the first page gets disposed. Subsequent state updates (using setState()) then fail.
I've overridden the dispose() method of the state object for the first page so that it prints a message when disposed. It's getting disposed as soon as I hit the third tab. I can't find documentation on why Flutter disposes state objects. (Plenty on lifecycle but not the reasons for progressing through the stages.)
Nothing unusual about setting up the tabs, I don't think.
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text(title),
bottom: TabBar(
tabs: [
// Use these 3 icons on the tab bar.
Tab(icon: Icon(Icons.tune)),
Tab(icon: Icon(Icons.access_time)),
Tab(icon: Icon(Icons.settings)),
],
),
),
body: TabBarView(
children: [
// These are the 3 pages relating to to the tabs.
ToolPage(),
TimerPage(),
SettingsPage(),
],
The pages themselves are pretty simple. No animation. Just switches and sliders, etc. I think about the only departures I've made from the code examples I've seen are that I've made the main app widget stateful, I've extended the tab pages to support wantKeepAlive() and I override wantKeepAlive to set it to true (thought that might help), and I call setState() on the first two tabs from an external object, which Android Studio flags with a weak warning. State on the first two pages gets updated when reading from a websocket this app opens to a remote server. Upon further testing I've noticed it only happens only when I tab from the first to the third page. Going from first to second or second to third does not trigger the dispose.
I would expect the State object associated with a StatefulWidget to stay around and with wantKeepAlive = true don't understand why it's being disposed when I click to the third tab, especially because it doesn't happen when I click to the second or from the second to third.
This happens because TabBarView doesn't always show all tabs. Some may be outside of the screen boundaries.
In that case, the default behavior is that Flutter will unmount these widgets to optimize resources.
This behavior can be changed using what Flutter calls "keep alive".
The easiest way is to use AutomaticKeepAliveClientMixin mixin on a State subclass contained inside your tab as such:
class Foo extends StatefulWidget {
#override
_FooState createState() => _FooState();
}
class _FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
#override
bool wantKeepAlive = true;
#override
Widget build(BuildContext context) {
super.build(context);
return Container();
}
}
This tells Flutter that Foo should not be disposed when it leaves the screen.