Android Programjaim

Android, Flutter/Dart, Kotlin, Java, Unity, HarmonyOS

Flutter provider architecture

2020. január 08. 16:44 - lacas8282

A provider architecture az amit a Google IO 19 ajanl Flutter ala, igy most ezt is megtanuljuk egyszeruen.
A Google amugy elkezdett egy sajat Provide package gyartasaba, de a Provider annyira jo lett, hogy felkaroltak es a sajatjukat nem is hasznaljak (community edition) Legalabbis a videoban ez hangzik el:D

Rogton a video:


Es akkor egy kis sajat szosszenet.

A Flutter provider package-rol lesz szo: https://pub.dev/packages/provider

Mi a franc ez?:D Egy otvozet a dependency injection es az allapotkezeles kozott, widgetektol widgeteknek!

Kezdjunk is kodolasnak!

Berdobjuk pubspec.yaml-be a:

provider: ^4.0.1


-t majd get

main.dart-ba ez lesz:


import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_provider_sample/counter.dart';
import 'package:flutter_provider_sample/counter_page.dart';
import 'package:provider/provider.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: Consumer<Counter>(
builder: (context, counter, _) {
return MaterialApp(
home: const CounterPage(),
);
},
),
);
}
}


A szokasos kis counter appunkon mutatjuk be hogyan csinaljak ezt a providernel a nagyok. MyApp root widgetunk van, szokasos... Az elso widget egy Multiprovider widget (ellato/biztosito) lesz, amiben felsorolhatjuk milyen providereket hasznalunk es melyik class-al (celszeru rogton multival kezdeni nagy appoknal). Itt most csak egy Counter osztalyt, amit majd kesobb definialunk a counter.dart file-ban.

ChangeNotifierProvider: egy widget, ami biztosit egy peldanyt a ChangeNotifier osztalybol a leszarmazottainak. Mellesleg eleg okos hozza, hogy csak akkor buildelje ujra az osztalyt, ha abszolut szukseges. Plusz automatikus kezeli a dispose-t/destroy-at az osztalynak, ha mar nem kell.

Tobb infora nem terek most ki, olvashato ezen a linken:  https://pub.dev/packages/provider#-readme-tab-

Consumer: (fogyaszto) -ba kerul maga az a resz, amivel mar hasznalni is tudjuk a biztositott peldanyt.

Es akkor jojjenek a belso osztalyok (counter.dart):

import 'package:flutter/widgets.dart';

class Counter with ChangeNotifier {
int _count = 0;

int get count => _count;

void increment() {
_count++;
notifyListeners();
}

void decrement()
_count--;
notifyListeners();
}
}


A Counter ugye a ChangeNotifierProvider build-jeben kerul be a kepbe, ezert a with keyworddel meghivjuk ra a ChangeNotifier -t. (with-rol olvashatsz a neten meg a mixin keyword-ekrol)

Az osztaly ugy gondolom egyertelmu. van egy _count valtozoja, ami privat es egy getter-e, amivel lekerjuk.
Van dec/inc method-ja. Ami utana hivasra kerul az az erdekesebb: notifyListeners();

Ez rogton erdekes lehet azoknak, akik nativ androidoztak mar, a listanal kell ott hasonlokeppen meghivni, ha tortent valtozas. Ez siman egy listener/observer pattern, ami kb egy event, ami kozli, hogy valtozas tortent.

Observer/listenerbe most nem mennek bele melyebben, eleg ennyit tudni most errol.

counter_page.dart:

class CounterPage extends StatelessWidget {
const CounterPage({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const CounterLabel(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const DecrementCounterButton(),
const IncrementCounterButton(),
],
),
],
)),
);
}
}

class DecrementCounterButton extends StatelessWidget {
const DecrementCounterButton({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () => Provider.of<Counter>(context, listen: false).decrement(),
tooltip: 'Decrement',
child: const Icon(Icons.remove),
);
}
}

class IncrementCounterButton extends StatelessWidget {
const IncrementCounterButton({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () => Provider.of<Counter>(context, listen: false).increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
);
}
}

class CounterLabel extends StatelessWidget {
const CounterLabel({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context);
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text('${counter.count}', style: Theme.of(context).textTheme.display1),
],
);
}
}

 

Tehat egy CounterPage osztaly lesz benne, a megjelenito reteg. Mindent kirakott emberunk widget-be kulon osztalyba, es a konstruktorjait const-al ellatta, igyis hivja meg oket.

Miert?

Hat hogy ne kelljen mindig mindent ujrabuildelni, optimalizalas. Viszont a dinamikus tartalom valtozik az observer miatt. Vagyis csak az a widget fog ujrabuildelodni, ami valtozik.

     onPressed: () => Provider.of<Counter>(context, listen: false).decrement(),

Provider-ben levo Counter osztalyra hivatkozunk es a funklciot meghivjuk (amit akarunk).

    final counter = Provider.of<Counter>(context);

itt pedig siman listenelunk ra. Mivel alapbol a listen = true.

ENNYI.

komment
Címkék: provider flutter

Android + Koin + Kotlin

2020. január 08. 10:04 - lacas8282

A Koinrol fogok beszelni kicsit. Fel eve kb android nativoztam utoljara, azota dartsolok/flutterezek kemenyen.

A Koin-t meg nem igazan hasznaltam, de most egy pillantast kellett vennem ra egy project erejeig (amit at kene irnom)

Ezert most felfedeztem, es lassuk mi is ez, mit kell tudni rola.

https://insert-koin.io/

A bemutatkozo oldal azt irja, ez egy pragmatikus dependency injection fremvork Kotlinosok szamara.

Kotlinban lett irva, nincs kod generalas, es ez egy DSL. Mi az a DSL? Ha rakeresunk a neten:

DSL: Domain Specific Language: domain specifikus nyelv. Tehat valami teruletre/reszfeladatra irt nyelv.

Dependency-k koze bemasoljuk a:

compile 'org.koin:koin-android:$koin_version


-t majd synceljuk.

A HelloRepository-s sample-t fogom leirni, ami az oldalukon is talalhato. De sokat kepzett android developerek kitalalhatjak a kodbol is, mivel viszonylag egyszeru, es kb 4-5 szot hasznal a definialasra.

Csinaljunk egy HelloRepo interface-t, es hozza egy implementaciot.

interface HelloRepository {
    fun giveHello(): String
}

class HelloRepositoryImpl() : HelloRepository {
    override fun giveHello() = "Hello Koin"
}


Csinaljunk egy presenter osztalyt hozza:

class HelloPresenter(val repo: HelloRepository) {

    fun sayHello() = "${repo.giveHello()} from $this"
}


Irjunk egy Koin modult erre:

val appModule = module {

    // single instance of HelloRepository
    single<HelloRepository> { HelloRepositoryImpl() }

    // Simple Presenter Factory
    factory { HelloPresenter(get()) }
}



Itt a HelloPresentert factory-kent definialjuk, hogy mindig mikor az Activity-nk egy uj presentert akar, ujat keszitsen

a Single kulcsszo nyilvanvaloan a Singletonra utal, egykere, stb.

Start Koin

Kell az appunkba egy Application class, ha meg nincsen.

class MyApplication : Application(){
    override fun onCreate() {
        super.onCreate()
        // Start Koin
        startKoin{
            androidLogger()
            androidContext(this@MyApplication)
            modules(appModule)
        }
    }
}


a MyApplication classunk kiterjeszti az Application osztalyt, es az onCreate-jebe beledobjuk  a startKoin-t, amibe deklaraljuk a modulokat (is).

Injektaljuk a dependenciakat (fecskendezzuk be a fuggosegeket :P)

A Prezentalo osztalyt bele kell injektalni ugye az Activity-nkbe.

class HelloActivity : AppCompatActivity() {

    // Lazy injected HelloPresenter
    val helloPresenter: HelloPresenter by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //...
    }
}


refaktoraltam az osztalyok neveit a jobb erthetoseg kedveert, altalaban az osszetartozo nevekkel latjuk el (prefixben) az egyazon dolgokra utalo cuccokat. A peldaban meg nem igy volt...

Tehat egyszeruen a by delegate kulcsszoval injektaljuk be az osztalyt az Activitybe.

Ez a by delegate funkcio teszi lehetove, hogy a Koin osztaly peldanyokat 'elerjuk'.

Mi az a get()?

A get() funkcio itt azert van, hogy direktben tudjuk a peldanyt meghivni (csak a kotlin annyira okos, hogy latni fogja mit kell odaraknia:))

 Ui.: Video a Koin alkotojaval, Arnaud-al:

komment
Címkék: android koin kotlin
süti beállítások módosítása