Jonny Borges
Committed by GitHub

Merge branch 'master' into null-safety

... ... @@ -214,7 +214,7 @@ Obx(() => Text("${controller.name}"));
### 关于状态管理的更多细节
**关于状态管理更深入的解释请查看[这里](./documentation/zh_CN/state_management.md)。在那里你将看到更多的例子,以及简单的阶段管理器和响应式状态管理器之间的区别**
**关于状态管理更深入的解释请查看[这里](./documentation/zh_CN/state_management.md)。在那里你将看到更多的例子,以及简单的状态管理器和响应式状态管理器之间的区别**
你会对GetX的能力有一个很好的了解。
... ...
... ... @@ -246,6 +246,28 @@ print(Get.parameters['user']);
// out: 34954
```
or send multiple parameters like this
```dart
Get.toNamed("/profile/34954?flag=true&country=italy");
```
or
```dart
var parameters = <String, String>{"flag": "true","country": "italy",};
Get.toNamed("/profile/34954", parameters: parameters);
```
On second screen take the data by parameters as usually
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
print(Get.parameters['country']);
// out: 34954 true italy
```
And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (you can call your routes directly from your BLoC or Controller class), and when your app is compiled to the web, your routes will appear in the url <3
### Middleware
... ...
... ... @@ -242,7 +242,21 @@ Y en la segunda pantalla tome los datos por parámetro
```dart
print(Get.parameters['user']);
// out: 34954
// salida: 34954
```
o envie multiples parametros de la siguiente manera
```dart
Get.toNamed("/profile/34954?flag=true");
```
En la segunda pantalla tome los parametros como lo haria normalmente
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// salida: 34954 true
```
Y ahora, todo lo que necesita hacer es usar Get.toNamed() para navegar por sus rutas nombradas, sin ningún contexto (puede llamar a sus rutas directamente desde su clase BLoC o Controller), y cuando su aplicación se compila para web, sus rutas aparecerán en la url del navegador <3
... ...
... ... @@ -247,6 +247,20 @@ print(Get.parameters['user']);
// donne: 34954
```
ou envoyer plusieurs paramètres comme celui-ci
```dart
Get.toNamed("/profile/34954?flag=true");
```
Sur le deuxième écran, prenez les données par paramètres comme d'habitude
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// donne: 34954 true
```
Et maintenant, tout ce que vous avez à faire est d'utiliser Get.toNamed() pour parcourir vos routes nommées, sans aucun contexte (vous pouvez appeler vos routes directement à partir de votre classe BLoC ou Controller), et lorsque votre application est compilée sur le Web, vos routes apparaîtront dans l'url <3
### Middleware
... ...
... ... @@ -248,6 +248,21 @@ print(Get.parameters['user']);
// keluaran: 34954
```
atau kirim beberapa parameter seperti ini
```dart
Get.toNamed("/profile/34954?flag=true");
```
Pada layar kedua, ambil data berdasarkan parameter seperti biasanya
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// keluaran: 34954 true
```
Dan sekarang, yang anda perlu lakukan adalah menggunakan Get.toNamed() untuk bernavigasi ke named route anda, tanpa konteks (anda bisa memanggil route secara langsung dari kelas BLoC atau Controller), dan ketika aplikasi anda di-compile di web, route anda akan muncul di url <3
### Middleware
... ...
... ... @@ -246,6 +246,23 @@ print(Get.parameters['user']);
// 출력: 34954
```
또는 이와 같은 여러 매개 변수를 보냅니다.
```dart
Get.toNamed("/profile/34954?flag=true");
```
두 번째 화면에서 일반적으로 매개 변수별로 데이터를 가져옵니다.
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// 출력: 34954 true
```
이제 Get.toNamed()를 사용하여 어떤 context도 없이 명명된 라우트를 탐색하고 (BLoC 또는 Controller 클래스로 부터 직접 라우트를 호출할 수 있음) 앱이 웹으로 컴파일되면 경로는 url에 표시됩니다. <3
### 미들웨어
... ...
... ... @@ -322,9 +322,26 @@ Get.toNamed("/segunda/34954");
Na segunda tela receba os dados usando `Get.parameters[]`
```dart
print(Get.parameters['user']); // valor: 34954
print(Get.parameters['user']);
// valor: 34954
```
ou envie vários parâmetros como este
```dart
Get.toNamed("/profile/34954?flag=true");
```
Na segunda tela, pegue os dados por parâmetros normalmente
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// valor: 34954 true
```
E agora, tudo que você precisa fazer é usar `Get.toNamed)` para navegar por suas rotas nomeadas, sem nenhum `context` (você pode chamar suas rotas diretamente do seu BLoc ou do Controller), e quando seu aplicativo é compilado para a web, suas rotas vão aparecer na url ❤
#### Middleware
... ...
... ... @@ -246,6 +246,22 @@ print(Get.parameters['user']);
// out: 34954
```
или отправьте несколько таких параметров
```dart
Get.toNamed("/profile/34954?flag=true");
```
На втором экране взять данные по параметрам как обычно.
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// out: 34954 true
```
И теперь все, что вам нужно сделать, это использовать Get.toNamed() для навигации по именованным маршрутам без какого-либо контекста (вы можете вызывать свои маршруты непосредственно из класса BLoC или контроллера), а когда ваше приложение будет скомпилировано в Интернете, ваше маршруты появятся в url <3
### Middleware
... ...
... ... @@ -243,6 +243,21 @@ print(Get.parameters['user']);
// out: 34954
```
或像这样发送多个参数
```dart
Get.toNamed("/profile/34954?flag=true");
```
在第二个屏幕上,通常按参数获取数据
```dart
print(Get.parameters['user']);
print(Get.parameters['flag']);
// out: 34954 true
```
现在,你需要做的就是使用Get.toNamed()来导航你的别名路由,不需要任何context(你可以直接从你的BLoC或Controller类中调用你的路由),当你的应用程序被编译到web时,你的路由将出现在URL中。
### 中间件
... ...
... ... @@ -343,25 +343,24 @@ ListView.builder (
```dart
// model
// 我们将使整个类成为可观察的,而不是每个属性。
class User() {
User({this.name = '', this.age = 0});
String name;
int age;
class User{
User({this.name = '', this.age = 0});
String name;
int age;
}
// controller
final user = User().obs;
//当你需要更新user变量时。
user.update( (user) { // 这个参数是你要更新的类本身。
user.name = 'Jonny';
user.age = 18;
user.name = 'Jonny';
user.age = 18;
});
// 更新user变量的另一种方式。
user(User(name: 'João', age: 35));
// view
Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"));
// 你也可以不使用.value来访问模型值。
user().name; // 注意是user变量,而不是类变量(首字母是小写的)。
```
... ... @@ -410,7 +409,7 @@ interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
这个`condition`定义了`callback`函数何时执行。
所有worker都会返回一个`Worker`实例,你可以用它来取消(通过`dispose()`)worker。
- **`ever`**
每当_Rx_变量发出一个新的值时,就会被调用。
... ... @@ -666,7 +665,7 @@ GetBuilder<Controller>(
```dart
GetBuilder<Controller>(
id: 'text' 、、这里
id: 'text', //这里
init: Controller(), // 每个控制器只用一次
builder: (_) => Text(
'${Get.find<Controller>().counter}', //here
... ...
... ... @@ -138,7 +138,7 @@ class GetHttpClient {
url: uri,
headers: headers,
bodyBytes: bodyStream,
contentLength: bodyBytes!.length,
contentLength: bodyBytes?.length ?? 0,
followRedirects: followRedirects,
maxRedirects: maxRedirects,
decoder: decoder,
... ... @@ -249,7 +249,8 @@ class GetHttpClient {
method: 'get',
url: uri,
headers: headers,
decoder: decoder ?? (defaultDecoder as Decoder<T>?),
decoder: decoder ?? (defaultDecoder as Decoder<T>),
contentLength: 0,
));
}
... ...
... ... @@ -93,9 +93,16 @@ class ParseRouteTree {
);
}
Map<String, String?> _parseParams(String path, PathDecoded routePath) {
final params = <String, String?>{};
Match? paramsMatch = routePath.regex.firstMatch(path);
var idx = path.indexOf('?');
if (idx > -1) {
path = path.substring(0, idx);
final uri = Uri.tryParse(path);
params.addAll(uri.queryParameters);
}
Match paramsMatch = routePath.regex.firstMatch(path);
for (var i = 0; i < routePath.keys.length; i++) {
var param = Uri.decodeQueryComponent(paramsMatch![i + 1]!);
... ...
... ... @@ -199,6 +199,41 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> {
fn(_value);
subject.add(_value);
}
/// Following certain practices on Rx data, we might want to react to certain
/// listeners when a value has been provided, even if the value is the same.
/// At the moment, we ignore part of the process if we `.call(value)` with
/// the same value since it holds the value and there's no real
/// need triggering the entire process for the same value inside, but
/// there are other situations where we might be interested in
/// triggering this.
///
/// For example, supposed we have a `int seconds = 2` and we want to animate
/// from invisible to visible a widget in two seconds:
/// RxEvent<int>.call(seconds);
/// then after a click happens, you want to call a RxEvent<int>.call(seconds).
/// By doing `call(seconds)`, if the value being held is the same,
/// the listeners won't trigger, hence we need this new `trigger` function.
/// This will refresh the listener of an AnimatedWidget and will keep
/// the value if the Rx is kept in memory.
/// Sample:
/// ```
/// Rx<Int> secondsRx = RxInt();
/// secondsRx.listen((value) => print("$value seconds set"));
///
/// secondsRx.call(2); // This won't trigger any listener, since the value is the same
/// secondsRx.trigger(2); // This will trigger the listener independently from the value.
/// ```
///
void trigger([T v]) {
var firstRebuild = this.firstRebuild;
value = v;
// If it's not the first rebuild, the listeners have been called already
// So we won't call them again.
if (!firstRebuild) {
subject.add(v);
}
}
}
/// Rx class for `bool` Type.
... ...
... ... @@ -95,4 +95,38 @@ void main() {
await Future.delayed(Duration.zero);
expect(count, 555);
});
test('Rx same value will not call the same listener when `call`', () async {
var reactiveInteger = RxInt(2);
var timesCalled = 0;
reactiveInteger.listen((newInt) {
timesCalled++;
});
// we call 3
reactiveInteger.call(3);
// then repeat twice
reactiveInteger.call(3);
reactiveInteger.call(3);
await Future.delayed(Duration(milliseconds: 100));
expect(1, timesCalled);
});
test('Rx same value will call the listener when `trigger`', () async {
var reactiveInteger = RxInt(2);
var timesCalled = 0;
reactiveInteger.listen((newInt) {
timesCalled++;
});
// we call 3
reactiveInteger.trigger(3);
// then repeat twice
reactiveInteger.trigger(3);
reactiveInteger.trigger(3);
await Future.delayed(Duration(milliseconds: 100));
expect(3, timesCalled);
});
}
... ...