@nguyen.thanh.minhb
Cái này là mình đọc từ code ra. Có vẻ như tác giả để như vậy để dễ hình dung cho người mới nhưng như thế thì mình nghĩ là nên note lại.
Trong Flutter thì mình hiểu có 2 loại Element chính là ComponentElement và RenderObjectElement. RenderObjectElement thì cung cấp RenderObject còn ComponentElement thì gián tiếp cung cấp RenderObject thông qua việc giúp định nghĩa nên cấu trúc của ElementTree. ComponentElement bao gồm 3 elements nhỏ hơn là StatelessElement (Chả làm gì ngoài việc gọi hàm build của widget), StatefulElement (Làm nhiều hơn một tí bằng cách quản lý vòng đời của State), và ProxyElement (Cung cấp ProxyWidget là widget mặc định có 1 final child và không có hàm build())
đúng là để an toàn nhất thì nên dùng 1 user độc lập thay vì tận dụng user node vì có thể user node mà người ta tạo sẵn họ còn cho thêm nhiều quyền khác nữa (ví dụ có quyền sudo chẳng hạn)
tạo 1 user mới, độc lập, chỉ có vừa đủ quyền chạy app của chúng ta là được
khả năng là bạn đã quên đoạn Note mình nói ở phần setup authentication cho MongoDB, đó là cần clear DB cũ (DB lúc chưa có authentication), vì nếu không thì khi chạy lên phần authentication sẽ không nhận vì tên database của ta trùng nhau, Mongo thấy DB cũ vẫn có nên sẽ không làm gì cả.
Mình vừa update cách xóa volume cho MongoDB trên Windows, bạn check lại phần authentication cho Mongo trong bài nhé.
@subhopefully
có framework mà dùng là ngon rồi bạn.
Trước mình từng làm CI2, symfony 1.4 doc tìm còn khó, cơ mà vẫn học đc rất nhiều thứ
cho dự án php7.4.9 lastest version mà bạn phải code thuần thì còn khổ hơn.
@manh11235 Wow, lần vào Container thì đúng như bạn nói, nó tạo RenderObject nhờ tạo thằng ColoredBox là một RenderObjectElement trong hàm build. Thảo nào, doc nó nói ComponentElement tạo gián tiếp RenderObject thông qua thằng Element khác, thằng ColoredBox là thằng gọi hàm createRenderObject, ko phải thằng Container Element gọi.
@nguyen.thanh.minhb mình cũng từng đọc qua https://medium.com/flutter-community/flutter-what-are-widgets-renderobjects-and-elements-630a57d05208 , nhưng vì k hiểu được rõ ràng có lẽ do trình tiếng anh toàn phải google nên mình chủ yếu lần theo các class đi theo nó (commander + B ).
ví dụ : Container -> StatelessWidget -> tạo ra StatelessElement , kế thừa từ ComponentElement -> Vào ComponentElement thì hàm mount không gọi widget.createRenderObject.
Ngược lại: Column -> Flex, kế thừa từ MultiChildRenderObjectWidget -> taọ ra MultiChildRenderObjectElement , kế thừa từ RenderObjectElement. hàm mount gọi widget.createRenderObject.
Nhưng ComponentElement không gọi widget.createRenderObject thì để tạo nên RenderObject tree thì làm thế nào. Cái này lần theo hàm build của Container. Nó trả về ví dụ như ColoredBox -> kế thừa từ RenderObjectWidget-> tạo ra RenderObjectElement . Suy ra ComponentElement cũng được tạo ra từ RenderObjectElement
Mấy chỗ như DecoratedBox, Padding, Column bị lộn thì phải. 3 widget này kế thừa từ RenderObjectWidget, RenderObjectWidget tạo ra RenderObjectElement. Còn StatelessElement , StatefulElement hay InheritedElement là ComponentElement.
Có thể chia thành 2 loại element chính là
1.ComponentElement ( StatelessElement , StatefulElement hay InheritedElement ). Loại này không tạo RenderObject
2.RenderObjectElement (Center, Padding,...).Loại này mới tạo RenderObject bằng cách gọi widget.createRenderObject trong hàm mount
voidmain(){final userA =User(1,'Minh');final userB =User(1,'Minh');// Toán tử == sẽ so sánh giá trịprint(userA == userB);// true vì cả userA và userB đều có id là 1 và name là Minh// hàm identical sẽ kiểm tra xem userA với userB có cùng trỏ đến 1 object khôngprint(identical(userA, userB));// false vì userA và userB không cùng trỏ đến 1 objectfinal userC = userA;// userC trỏ đến cùng object với userAprint(identical(userA, userC));// nên hàm identical print ra true}classUser{User(this.id,this.name);final int id;finalString name;// ta sẽ override lại toán tử ==// tức là ta định nghĩa lại "Khi nào thì 2 User gọi là == nhau)@override
bool operator==(Object other){// Khi 2 user có cùng id và cùng name thì chúng bằng nhaureturn id ==(other asUser).id && name ==(other asUser).name;}}
Câu 2: tại sao ngay từ đầu trong cái source này https://dartpad.dev/cbcf93cfd5655c514af90e87010be7c3 , mình sử dụng UniqueKey nhưng State của widget Tile vẫn được giữ như cũ. Bằng chứng là màu sắc của Tile nó nó không bị reset thành 1 màu mới. Còn trong ví dụ lần này thì một State mới của TextField đã được tạo ra.
Trả lời: Đầu tiên first build, thì object _MyHomePageState được khởi tạo lần đầu và biến listTile trong _MyHomePageState cũng được khởi tạo lần đầu. Giả sử lúc khởi tạo lần đầu này object Tile thứ nhất trong listTile có màu đen và key là 1, object Tile thứ 2 có màu đỏ và key là 2. Khi gọi hàm setState, nó chỉ đơn giản là swap 2 object Tile này chứ không tạo ra một object Tile mới thay thế. Hơn nữa _MyHomePageState cũng không có bị destroy nên biến listTile cũng không được tạo mới. Tóm lại, 2 object Tile được tạo từ đầu, không bao giờ bị destroy nên tất nhiên Key nó sẽ không thay đổi. Trước key là 1, sau khi rebuild vẫn là 1, trước là 2 thì sau vẫn là 2, vì vậy Element so sánh thấy Key trước và sau đều không đổi nên State được bảo toàn. Còn trong ví dụ 2 TextField thì khi rebuild 1 object TextField mới được tạo ra, nên trước đó key có thể là 1, sau khi rebuild key có thể là 3. Vì vậy, trước và sau khi rebuild, Element so sánh thấy key khác nhau nên destroy chính nó, tạo ra Element mới và State mới.
THẢO LUẬN
@thienhavodinh cảm ơn bạn, mình đã có cái nhìn sâu hơn về chủ đề này
@nguyen.thanh.minhb Cái này là mình đọc từ code ra. Có vẻ như tác giả để như vậy để dễ hình dung cho người mới nhưng như thế thì mình nghĩ là nên note lại.
Trong Flutter thì mình hiểu có 2 loại
Elementchính làComponentElementvàRenderObjectElement.RenderObjectElementthì cung cấpRenderObjectcònComponentElementthì gián tiếp cung cấpRenderObjectthông qua việc giúp định nghĩa nên cấu trúc củaElementTree.ComponentElementbao gồm 3 elements nhỏ hơn là StatelessElement (Chả làm gì ngoài việc gọi hàm build của widget), StatefulElement (Làm nhiều hơn một tí bằng cách quản lý vòng đời của State), và ProxyElement (Cung cấp ProxyWidget là widget mặc định có 1 final child và không có hàmbuild())cám ơn bạn đã chia sẻ,
đúng là để an toàn nhất thì nên dùng 1 user độc lập thay vì tận dụng user
nodevì có thể usernodemà người ta tạo sẵn họ còn cho thêm nhiều quyền khác nữa (ví dụ có quyềnsudochẳng hạn)tạo 1 user mới, độc lập, chỉ có vừa đủ quyền chạy app của chúng ta là được
chào bạn mình đã check lại,
khả năng là bạn đã quên đoạn Note mình nói ở phần setup authentication cho MongoDB, đó là cần clear DB cũ (DB lúc chưa có authentication), vì nếu không thì khi chạy lên phần authentication sẽ không nhận vì tên database của ta trùng nhau, Mongo thấy DB cũ vẫn có nên sẽ không làm gì cả.
Mình vừa update cách xóa volume cho MongoDB trên Windows, bạn check lại phần authentication cho Mongo trong bài nhé.
Mình đã test lại trên Win 10 và chạy ngon
@Croud141

cảm ơn bạn đã ủng hộ, mình sẽ cố gắng ra bài mới sớm
@subhopefully có framework mà dùng là ngon rồi bạn.
Trước mình từng làm CI2, symfony 1.4 doc tìm còn khó, cơ mà vẫn học đc rất nhiều thứ
cho dự án php7.4.9 lastest version mà bạn phải code thuần thì còn khổ hơn.
đúng rồi bạn. trang nào phải có cơ sở và thông tin thì nó mới detect đc chứ. còn mình mà cố tình dấu đi thì tool cũng bó tay thôi
@thienhavodinh Hình đó mình lấy từ nguồn này, tác giả thuộc Flutter team nên cũng là một nguồn đáng tin chứ nhỉ. Hy vọng bác cho ý kiến để mọi người cùng học hỏi. https://medium.com/flutter/how-to-create-stateless-widgets-6f33931d859
@manh11235 Wow, lần vào Container thì đúng như bạn nói, nó tạo RenderObject nhờ tạo thằng ColoredBox là một RenderObjectElement trong hàm build. Thảo nào, doc nó nói ComponentElement tạo gián tiếp RenderObject thông qua thằng Element khác, thằng ColoredBox là thằng gọi hàm createRenderObject, ko phải thằng Container Element gọi.
@nguyen.thanh.minhb mình cũng từng đọc qua https://medium.com/flutter-community/flutter-what-are-widgets-renderobjects-and-elements-630a57d05208 , nhưng vì k hiểu được rõ ràng có lẽ do trình tiếng anh toàn phải google nên mình chủ yếu lần theo các class đi theo nó (commander + B ). ví dụ : Container -> StatelessWidget -> tạo ra StatelessElement , kế thừa từ ComponentElement -> Vào ComponentElement thì hàm mount không gọi widget.createRenderObject. Ngược lại: Column -> Flex, kế thừa từ MultiChildRenderObjectWidget -> taọ ra MultiChildRenderObjectElement , kế thừa từ RenderObjectElement. hàm mount gọi widget.createRenderObject.
Nhưng ComponentElement không gọi widget.createRenderObject thì để tạo nên RenderObject tree thì làm thế nào. Cái này lần theo hàm build của Container. Nó trả về ví dụ như ColoredBox -> kế thừa từ RenderObjectWidget-> tạo ra RenderObjectElement . Suy ra ComponentElement cũng được tạo ra từ RenderObjectElement
Hình đó mình lấy từ nguồn này, tác giả thuộc Flutter team. https://medium.com/flutter/how-to-create-stateless-widgets-6f33931d859
Còn 2 loại Element thì đúng như bạn nói, một thằng tạo trực tiếp, một thằng tạo gián tiếp. Để mình update. Cảm ơn bạn nhé
Bạn có nguồn nào nói về cái này không. Mình tìm hiểu từ sách, nó không nói kĩ đến mức này. Cảm ơn bạn
Mấy chỗ như DecoratedBox, Padding, Column bị lộn thì phải. 3 widget này kế thừa từ RenderObjectWidget, RenderObjectWidget tạo ra RenderObjectElement. Còn StatelessElement , StatefulElement hay InheritedElement là ComponentElement. Có thể chia thành 2 loại element chính là 1.ComponentElement ( StatelessElement , StatefulElement hay InheritedElement ). Loại này không tạo RenderObject 2.RenderObjectElement (Center, Padding,...).Loại này mới tạo RenderObject bằng cách gọi widget.createRenderObject trong hàm mount
Sự khác nhau giữa so sánh == và identical
Câu này có bị ngược k tác giả ơi "Để tạo chữ ký, người gửi sẽ dùng private key và người nhận sẽ dùng public key để xác thực chữ ký đó" ?
good
@maitrungduc1410 đã thông não thành công, cảm ơn chia sẻ của a.
Bài viết rất cụ thể. Bạn Anh cho hỏi code viết labelText như thế nào? Trong bài ko thấy. Tks
Câu 2: tại sao ngay từ đầu trong cái source này https://dartpad.dev/cbcf93cfd5655c514af90e87010be7c3 , mình sử dụng UniqueKey nhưng State của widget Tile vẫn được giữ như cũ. Bằng chứng là màu sắc của Tile nó nó không bị reset thành 1 màu mới. Còn trong ví dụ lần này thì một State mới của TextField đã được tạo ra.
Trả lời: Đầu tiên first build, thì object
_MyHomePageStateđược khởi tạo lần đầu và biếnlistTiletrong_MyHomePageStatecũng được khởi tạo lần đầu. Giả sử lúc khởi tạo lần đầu này objectTilethứ nhất tronglistTilecó màu đen và key là 1, objectTilethứ 2 có màu đỏ và key là 2. Khi gọi hàmsetState, nó chỉ đơn giản là swap 2 objectTilenày chứ không tạo ra một objectTilemới thay thế. Hơn nữa_MyHomePageStatecũng không có bị destroy nên biếnlistTilecũng không được tạo mới. Tóm lại, 2 objectTileđược tạo từ đầu, không bao giờ bị destroy nên tất nhiên Key nó sẽ không thay đổi. Trước key là 1, sau khi rebuild vẫn là 1, trước là 2 thì sau vẫn là 2, vì vậy Element so sánh thấy Key trước và sau đều không đổi nên State được bảo toàn. Còn trong ví dụ 2 TextField thì khi rebuild 1 object TextField mới được tạo ra, nên trước đó key có thể là 1, sau khi rebuild key có thể là 3. Vì vậy, trước và sau khi rebuild, Element so sánh thấy key khác nhau nên destroy chính nó, tạo ra Element mới và State mới.