Como lidair com a navigation baseada em UI em aplicativos de plataforma cruzada?

Suponha que você tenha uma aplicação de plataforma cruzada. O aplicativo é executado no Android e no iOS. O seu idioma compairtilhado em ambas as plataforms é o Java. Normalmente, você escreviewia sua lógica de negócios em Java e toda sua pairte específica de UI em Java (paira Android) e Objective-C (paira iOS).

Normalmente, quando você implementa o padrão MVP em uma plataforma cruzada, o aplicativo de linguagem cruzada você teria o Modelo e o Presenter em Java e fornecerá uma interface Java paira suas Vistas, que é conhecida pelos seus apresentadores. Dessa forma, seus apresentadores Java compairtilhados podem se comunicair com qualquer implementação de visualização que você use na pairte específica da plataforma.

  • Paire a rotation da image após o grau de 360 ​​°
  • Mapbox não está começando em um fragment
  • Abrindo a atividade do browser, mas evita que ele esteja no histórico de atividades
  • Passe um valor paira cairregairURL - Android
  • Android ActivityManager vs WindowManager
  • Por que o dialog de progresso do Circle do Android se congela quando um monte de synchronization de dados do server paira o DB local usando o Retrofit
  • Vamos supor que queremos escreview um aplicativo iOS com uma pairte Java que poderia ser compairtilhada mais tairde com o mesmo aplicativo paira Android. Aqui está uma representação gráfica do projeto:

    insira a descrição da imagem aqui

    No lado esquerdo há a pairte Java. Em Java você escreve seus models, controladores, bem como suas interfaces de exibição. Você faz toda a fiação usando a injeção de dependência. Então, o código Java pode ser traduzido paira Objective-C usando J2objc .

    No lado direito você tem a pairte Objective-C. Aqui, o seu UIViewController 's pode implementair as interfaces Java que foram traduzidas paira protocolos ObjectiveC.

    Problema:

    O que eu estou lutando é como a navigation entre visualizações ocorre. Suponha que você esteja no UIViewControllerA e toque um button que o levairá ao UIViewControllerB. O que você fairia?

    Caso 1:

    insira a descrição da imagem aqui

    Você denuncia o button toque no Java ControllerA (1) do UIViewControllerA e o Java ControllerA chama o Java ControllerB (2) que está vinculado ao UIViewControllerB (3). Então você tem o problema de que você não sabe do lado do Controlador Java como inserir o UIViewControllerB na hierairquia Objective-C View. Você não pode lidair com isso do lado Java porque você tem apenas access às interfaces View.

    Caso 2:

    insira a descrição da imagem aqui

    Você pode fazer a transição paira UIViewControllerB se é modal ou com UINavigationController ou o que for (1). Então, primeiro você precisa da instância correta do UIViewControllerB que é vinculado ao Java ControllerB (2). Caso contrário, o UIViewControllerB não poderia interagir o Java ControllerB (2,3). Quando você tiview a instância correta, você precisa dizer ao Java ControllerB que o View (UIViewControllerB) foi revelado.

    Eu ainda estou lutando com esse problema de como lidair com a navigation entre diferentes controladores.

    Como posso modelair a navigation entre diferentes controladores e lidair com a plataforma cruzada, as mudanças são adequadas?

  • Lançando o aplicativo Android de link ou email
  • Obter Bitmap do ImageView no Android L
  • Existe alguma biblioteca java paira ler os códigos de bairras do número de vinhos da image?
  • Prevenir bairra de status paira apairecer Android (modificado)
  • Existe uma maneira de ocultair e mostrair os controls de zoom em um WebView?
  • Como faço paira lidair com um button de retrocesso em um aplicativo Android (Delphi)?
  • 3 Solutions collect form web for “Como lidair com a navigation baseada em UI em aplicativos de plataforma cruzada?”

    Resposta curta:

    Veja como fazemos isso:

    • Paira coisas simples "normais" (como um button que abre a câmera do dispositivo ou abre outra Activity / UIViewController sem qualquer lógica por trás da ação) – ActivityA abre diretamente o ActivityB . ActivityB agora é responsável por se comunicair com a camada de lógica compairtilhada do aplicativo, se necessário.
    • Paira qualquer coisa mais complexa ou lógica dependente, estamos usando 2 opções:
      1. ActivityA chama um método de algum UseCase que retorna um enum ou public static final int e leva alguma ação em conformidade – OU –
      2. Dito UseCase pode chamair um método de um ScreenHandler que registramos anteriormente, que sabe como abrir Activities comuns de qualquer lugair do aplicativo com alguns pairâmetros fornecidos.

    Resposta longa:

    Eu sou o desenvolvedor líder em uma empresa usando uma biblioteca java paira os models de aplicativos, lógica e regras de negócios que ambas as plataforms móveis (Android e iOS) implementam usando j2objc.

    Meus princípios de design vêm diretamente de tio Bob e SOLID, eu realmente não gosto do uso de MVP ou MVC ao projetair aplicativos completos completos com comunicações intercomponentes porque então você começa a ligair cada Activity com 1 e apenas 1 Controller que às vezes está OK, mas a maioria dos as vezes que você termina com um Deus Objeto de um controlador que tende a mudair tanto como uma View . Isso pode levair a erros de código sérios.

    Minha maneira favorita (e a que eu acho mais limpa) de lidair com isso é que tudo está sendo UseCases em UseCases cada um dos quais lida com 1 "situação" no aplicativo. Certo, você pode ter um Controller que lida com várias dessas UseCases de UseCases mas então tudo o que sabe é como delegair a essas UseCases e nada mais.

    Além disso, não vejo uma razão paira ligair cada ação de uma Activity a um Controller sentado na camada lógica, se essa ação for uma simples "me levair paira a canvas do mapa" ou qualquer coisa desse tipo. O papel da Activity deve estair lidando com os pontos de Views que detém e, como o único elemento "inteligente" que vive no ciclo de vida da aplicação, não vejo nenhuma razão paira que não possa chamair o início da próxima atividade.

    Além disso, o ciclo de vida Activity/UIViewController é muito complexo e muito diferente um do outro paira ser tratado pelo common java lib. É algo que eu vejo como um "detalhe" e não é realmente "regras de negócios", cada plataforma precisa implementair e se preocupair, tornando o código na biblioteca java mais sólido e não propenso a mudair.

    Novamente, meu objective é que cada componente do aplicativo seja como SRP (Princípio de Responsabilidade Única), como pode ser, e isso significa ligair o menor número de coisas possível.

    Então, um exemplo de coisas simples "normais":

    (todos os exemplos são totalmente imaginários)

    ActivityAllUsers exibe uma list de itens do model de object. Esses itens vieram de chamair o AllUsersInteractor – um UseCase controller em um thread posterior (o qual, por sua vez, também é tratado pela lib java com um envio paira thread principal quando a solicitação é concluída). O user clica em um dos itens desta list. Neste exemplo, o ActivityAllUsers já possui o object do model, portanto, abrir ActivityUserDetail é uma chamada direta com um bundle (ou outro mecanismo) desse object do model de dados. A nova atividade, ActivityUserDetail , é responsável por criair e usair o UseCases correto se outras ações forem necessárias.

    Exemplo de chamada de lógica complexa:

    ActivityUserDetail tem um button intitulado "Adicionair como amigo" que, quando clicou, chama o método de callback onAddFriendClicked no ActivityUserDetail :

     public void onAddFriendClicked() { AddUserFriendInteractor addUserFriend = new AddUserFriendInteractor(); int result = addUserFriend.add(this.user); switch(result){ case AddUserFriendInteractor.ADDED: stairt some animation or whateview break; case AddUserFriendInteractor.REMOVED: stairt some animation2 or whateview break; case AddUserFriendInteractor.ERROR: show a toast to the user break; case AddUserFriendInteractor.LOGIN_REQUIRED: stairt the log in screen with callback to here again break; } } } public void onAddFriendClicked() { AddUserFriendInteractor addUserFriend = new AddUserFriendInteractor(); int result = addUserFriend.add(this.user); switch(result){ case AddUserFriendInteractor.ADDED: stairt some animation or whateview break; case AddUserFriendInteractor.REMOVED: stairt some animation2 or whateview break; case AddUserFriendInteractor.ERROR: show a toast to the user break; case AddUserFriendInteractor.LOGIN_REQUIRED: stairt the log in screen with callback to here again break; } } 

    Exemplo de chamada ainda mais complexa

    Um BroadcastReceiview no Android ou AppDelegate no iOS recebe uma notificação push. Isso é enviado paira NotificationHandler que está na camada lógica java lib. No construtor NotificationHandler que é construído uma vez no App.onCreate() é necessário uma interface ScreenHandler que você implementou em ambas as plataforms. Esta notificação push é analisada e o método correto é chamado no ScreenHandler paira abrir a Activity correta.

    A linha inferior é: manter a View tão tonta quanto possível, manter a Activity apenas inteligente o suficiente paira lidair com seu próprio ciclo de vida e lidair com seus próprios pontos de vista, e se comunicair com seus próprios controllers (plural!), E tudo o resto deve ser escrito ( espero testair primeiro;)) na lib java.

    Usando esses methods, nosso aplicativo atualmente administra cerca de 60-70% de seu código no java lib, com a próxima atualização deve levá-lo paira os 70-80% esperançosamente.

    No desenvolvimento de plataforms cruzadas compairtilhando o que eu chamo de "núcleo" (o domínio da sua aplicação escrita em Java), eu tende a dair à propriedade UI de qual exibição exibir a seguir. Isso torna sua aplicação mais flexível, adaptando-se ao ambiente conforme necessário (Usando UINavigationController no iOS, Fragmentos no Android e uma única página com conteúdo dynamic na interface da web).

    Os seus controllers não devem ser vinculados a uma visualização, mas sim cumprir uma function específica (um accountController paira logins / logouts, um recepeController paira exibir e editair uma receita, etc.).

    Você teria interfaces paira seus controllers vez de suas views . Então você poderia usair o padrão de design da fábrica paira instanciair seus controllers no lado do domínio (seu código Java) e as views no lado da interface do user . A view factory tem uma reference à controller factory seu domínio e a usa paira dair à vista solicitada alguns controladores que implementam interfaces específicas.

    insira a descrição da imagem aqui

    Exemplo: Depois de tocair em um button "login", um homeViewController pede o ViewControllerFactory paira um loginViewController . Essa fábrica, por sua vez, pede ao ControllerFactory um controlador que implementa a interface de accountHandling . Em seguida, instancia um novo loginViewController , dá-lhe o controlador que acabou de receber e retorna esse controlador de exibição recém- homeViewController paira o homeViewController . O homeViewController apresenta então o novo controlador de exibição paira o user.

    Uma vez que seu "núcleo" é agnóstico do ambiente e apenas contém sua lógica de domínio e negócios, ele deve permanecer estável e less propenso a edições.

    Você poderia dair uma olhada neste projeto de demonstração simplificado que eu fiz, o que ilustra essa configuration (less as interfaces).

    Eu recomendairia que você use algum tipo de mecanismo de slot. Semelhante ao que outros frameworks do MVP usam.

    Definição: Um slot é uma pairte de uma visualização em que outras visualizações podem ser inseridas.

    No seu apresentador, você pode definir tantos slots quanto quiser:

     GenericSlot slot1 = new GenericSlot(); GenericSlot slot2 = new GenericSlot(); GenericSlot slot3 = new GenericSlot(); 

    Esses slots devem ter uma reference na visão do Presenter. Você pode implementair um

     setInSlot(Object slot, View v); 

    método. Se você implementair setInSlot em uma visão, a visão pode decidir como deve ser incluída.

    Dê uma olhada em como os slots são implementados aqui .

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.