[JAVA] Comparaison approfondie des implémentations Android et iOS

introduction

Il semble que. Cet article est l'article du 21e jour du Calendrier de l'Avent IS17er.

Cette fois, en commémoration de la sortie des deux versions iOS / Android de l'application de jeu d'étude appelée FF Multiplier, que je développais depuis longtemps, il semble qu'il était difficile de développer laquelle j'ai ressenti pendant le développement. Je voudrais faire une comparaison approfondie.

Cliquez ici pour l'appli

Je pense qu'il était courant pour les personnes qui développaient les deux d'exprimer leurs sentiments, donc cette fois je voudrais me concentrer sur la façon de réaliser techniquement une certaine fonction.

minuteur

Swift La minuterie dans Swift utilise essentiellement Timer (anciennement NSTimer). Si vous voulez faire la même chose toutes les quelques secondes

timer


Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.updateTime), userInfo: nil, repeats: true)

comme ça. Avec l'introduction de # selector, les fautes de frappe ont été réduites et, en gros, c'est très pratique car vous pouvez écrire en toute sécurité sans vous soucier des threads.

Java Même en Java, les minuteries sont essentiellement implémentées en utilisant la classe Timer. Cependant, comme vous pouvez le voir à partir de la liste lorsque vous googlez ʻAndroid timer et Java Timer, il y a plusieurs façons de passer la classe TimerTask à Timer`, ce qui peut être ennuyeux pour les débutants. ..

Cette fois, c'était un compte à rebours du jeu, donc au début je pensais utiliser la même classe appelée CountDownTimer, mais après un examen plus approfondi, il semble que cela présente l'inconvénient de ne pas mesurer exactement 1 seconde, Je me suis installé sur Timer. Si vous créez une classe distincte, la méthode d'écriture elle-même est similaire.

timer


timer.schedule(timerTask, 0, 1000);

Cependant, dans le cas d'Android, il est important de noter que le processus Timer est exécuté dans un thread séparé, donc le thread principal doit être appelé à partir du processus. À cet égard, j'ai senti que la minuterie Android était un peu difficile pour les débutants.

Disposition de la grille

iOS La disposition de grille que nous voyons cette fois est un moyen de créer une grille pure qui n'inclut pas une vue de défilement comme CollectionView en arrière-plan.

Comme méthode de réalisation sur iOS

Y a-t-il un succès? Cette fois, nous avons adopté StackView. Cependant, je pense que l'inconvénient est que cette fonctionnalité n'est pas rétrocompatible et ne fonctionne pas avant iOS 9. Cependant, j'ai pu l'arranger presque comme je l'avais prévu. C'est bien que la valeur par défaut soit centrée et étendue à l'ensemble.

Android Pour Android, bien sûr, utilisez LinearLayout. C'est une fonction qui existe depuis le début, elle fonctionne donc sur n'importe quel avion, et comme il existe de nombreux matériaux sur le réglage des ratios, il est bon que le coût d'apprentissage soit faible. Même si ce n'est pas le cas, cela peut être réalisé assez facilement car il a la même fonction appelée GridLayout.

C'est à vous de définir le centrage et l'expansion vers l'élément parent complet, mais il semble qu'Android, qui était en avance sur le jeu, sera mieux dans ce domaine.

Association

iOS Il est prudent de dire que les fichiers de mise en page (c'est-à-dire les storyboards) et les chaînes de code ne sont pas aussi faciles qu'iOS. À proprement parler, il peut y avoir des inconvénients tels que lorsque AutoLayout est appliqué et lorsqu'il est connecté au code dans le cycle de vie, mais fondamentalement, le coût d'apprentissage est très faible, ce qui est intéressant. Vous pouvez également associer une «@ IBAction» à plusieurs boutons et diviser le traitement par balise sur l'interface graphique.

Cependant, en ce qui concerne le traitement des boutons dans CustomView, c'est un peu délicat. Comme il n'est pas possible d'associer directement à partir du contrôleur de vue parent, il ne peut pas être réalisé sans une certaine ingéniosité dans le cas d'un traitement qui affecte les éléments du contrôleur de vue. Je viens de le trouver

--Créer un délégué

Dans mon cas, je pense que je préfère utiliser la troisième méthode exclusivement de nos jours. Autrement dit, dans CustomView

En vue personnalisée


var action: (()->())!

C'est une méthode pour le déclarer comme ça et passer le processus lors de son instanciation.

Android Sur Android, il existe essentiellement un fichier appelé R qui gère tout à la fois, et cela ressemble à enregistrer un identifiant à partir de xml et à récupérer des éléments en utilisant findViewById sur le code. Puisqu'il doit être écrit en code, c'est un peu gênant, mais à la place, si vous l'écrivez correctement, vous pouvez l'associer à tout moment.

De plus, dans le passé, l'événement ʻonClick était toujours fait avec setOnClickListener, mais Android Studio a officiellement rendu possible de définir la méthode ʻonClick à partir de xml.

Je pense que nous pouvons vraiment dire qu'il y a des avantages et des inconvénients dans ce domaine.

Police de caractère

iOS Lorsque vous utilisez une police, en particulier votre police préférée qui n'est pas incluse par défaut, vous pouvez l'utiliser à partir du code ou du storyboard en la plaçant dans le projet et en définissant les ressources du bundle de copie de la phase de construction sur iOS. C'est facile.

Android Les polices personnalisées sont un peu délicates pour Android. Vous devez d'abord mettre la police que vous souhaitez mettre dans les actifs, puis créer généralement une classe personnalisée pour l'élément dont vous souhaitez modifier la police. De plus, si vous le faites sans y penser, le fichier de police sera copié à chaque fois que vous l'utiliserez, vous devez donc créer quelque chose comme «FontHolder» et gérer «Typeface».

Il existe une bibliothèque appelée Calligraphy pour résoudre ce problème. Cela facilite la gestion sans créer de classes personnalisées.

Je veux vraiment qu'iOS vienne ici ... transpirer

Alerte

iOS Utilisez ʻUIAlertController` pour déclencher une alerte. Des éléments simples tels que des champs de texte peuvent être définis à partir du code. Par exemple, OK, bouton Annuler et une alerte de champ de texte

Alert


let alert = UIAlertController(title: "register name", message: "please set your username", preferredStyle: .alert)
alert.addTextField {
    textField in
    textField.placeholder = "user name"
}
alert.addAction(UIAlertAction(title: "OK", style: .default) {
    _ in
    let textfield = alert.textFields?.first
    if let name = textfield?.text {
        self.storage.set(name, forKey: "playername")
    }
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)

C'est facile.

Android Android est ʻAlerte Dialog`. Cependant, comme les champs de texte, etc. ne sont pas préparés, je vais créer du xml et l'appliquer.

AlertDialog


LayoutInflater inflater = LayoutInflater.from(gameActivity);
View dialog = inflater.inflate(R.layout.input_dialog, null);
final EditText editText = (EditText) 
dialog.findViewById(R.id.editNameText);
new AlertDialog.Builder(gameActivity).setTitle("please set your name").setView(dialog).setPositiveButton("ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    final String userName = editText.getText().toString();
                    sp.edit().putString("name", userName).commit();
                }
            }).show();

C'est un peu plus gênant, mais vous pouvez ajouter ce que vous aimez pour le faire, pour pouvoir dire que vous avez beaucoup de liberté.

Chose semblable à une vue contextuelle

iOS Le type de pop-up a beaucoup de restrictions telles que le fait d'avoir un élément parent s'il s'agit de l'élément par défaut, donc je pense qu'il est préférable d'utiliser une bibliothèque pour afficher la vue en haut.

C'est pourquoi j'ai utilisé ceci.

STZPoupupView

Si vous préparez une mise en page avec Storyboard ou xib, elle peut être affichée assez facilement.

Android D'un autre côté, je pense qu'il existe plusieurs façons de le réaliser sur Android, mais il existe une fonction appelée PopupWindow.

Cela vous permet de réaliser ce que vous voulez faire, même s'il existe quelques éléments de réglage.

Cependant, il peut être plus facile de personnaliser le AlertDialog pour cet élément ...

Manipulation de Firebase

Fondamentalement, les deux sont traités de la même manière, mais il existe des différences en fonction des caractéristiques de la langue en termes d'utilisation qui est assez facile à gérer. Par exemple, lors de l'inscription

Firebase/setvalue


ref.child("hello").child(device_id).setValue(["id": id, "rank": rank as NSNumber], andPriority: -newScore.score)

De cette façon, vous pouvez vous inscrire à l'aide de Dictionary sur iOS. D'autre part, Android peut être utilisé de la même manière en utilisant Map <String, Object>, mais cela est utilisé dans l'arbre de hachage et n'est pas purement standard, définissez donc la classe comme suit. main

Firebase/class


@IgnoreExtraProperties
public class DatabaseScore {
    public String id;
    public int rank;

    public DatabaseScore() {}

    public DatabaseScore(String id, int rank) {
        this.id = id;
        this.rank = rank;
    }

    public int getId() {
        return id;
    }

    public String getRank() {
        return rank;
    }
}

En passant une instance de ceci, le nom de la variable est automatiquement converti en clé et géré. Comme ça

Firebase/setvalue


ref.child("hello").child(id).setValue(databaseScore);

Lors de la lecture de la base de données, Swift est ʻobserve (.value, with: handler) et Android est ʻaddValueEventListener (valueEventListener). Chaque caractéristique est sortie. Il peut être lu dans le même format que lors de son enregistrement.

Traitement du royaume

Il existe une tendance similaire à la façon de gérer Realm avec Firebase.

Comparons la lecture et l'écriture simples. Tout d'abord, sur iOS, cela ressemble à ceci:

Modèle de royaume


import RealmSwift

final class Score: Object {
    dynamic var date = NSDate(timeIntervalSince1970: 1)
    dynamic var score: Int = 0
}

Tout d'abord, définissez le modèle avec ceci. Vous avez ajouté le modificateur dynamic à ce que vous vouliez enregistrer pour le traitement interne de Realm. Et

Écriture de royaume


let newScore = Score(value: ["date": NSDate(), "score": acceptedNum])
let realm = try! Realm()
try! realm.write {
    realm.add(newScore)
}

Si vous entrez dans le fil d'écriture avec try et ajoutez-le comme ceci

Charge de royaume


let scores = realm.objects(Score.self).sorted(byProperty: "score", ascending: false)

De cette façon, il était possible de récupérer ce qui avait été sauvegardé par la méthode appelée ʻobjects`.

Alors faisons la même chose sur Android. Ensuite, le modèle / écriture / lecture sera le suivant.

Modèle de royaume


import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

import java.util.Date;

public class ScoreModel extends RealmObject {
    private int score;
    private Date date;

    public void setScore(int score) {
        this.score = score;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Date getDate() {
        return date;
    }

    public int getScore() {
        return score;
    }
}

Écriture de royaume


final ScoreModel scoreModel = new ScoreModel();
scoreModel.setScore(correctCnt * 10);
scoreModel.setDate(cal.getTime());
Realm realm = Realm.getDefaultInstance();
realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        realm.copyToRealm(scoreModel);
    }
});

Charger le royaume


RealmResults<ScoreModel> results = realm.where(ScoreModel.class).findAllSorted("score", Sort.DESCENDING);

Le flux est le même, mais il est caractéristique qu'il soit nécessaire de définir d'abord getter et setter dans le modèle, en écrivant comme traitement asynchrone dans l'interface, et le résultat est renvoyé dans le type appelé RealmResults. Je pense.

Il est difficile de dire lequel est le meilleur, mais l'impression que Swift est plus concis est forte.

Inscription développeur

iOS C'est 11 800 yens par an. Le mode de paiement est la carte-cadeau ou le crédit de l'Apple Store, donc si vous n'avez pas de carte de crédit, vous pouvez vous rendre sur l'Apple Store chaque année.

Non, c’est cher. .. ..

Android Il n'y a pas de frais d'inscription autres que 25 $. Honnête! Le paiement se fait par carte de crédit ou carte de débit, mais il semble que les personnes qui n'ont pas de carte de crédit pourront payer comme une carte prépayée dans un dépanneur en utilisant le service VISA appelé V Preca.

Résumé

De nos jours, les applications pour smartphone sont devenues le pilier du développement d'applications, mais il semble qu'il soit encore assez difficile de réaliser des choses similaires avec les deux.

Surtout sous Android, il existe de nombreuses situations dans lesquelles vous devez être conscient des threads, et en Java, ce n'est pas nul, vous devez donc faire attention à cela. En revanche, si vous ne maîtrisez pas correctement iOS, le degré de liberté diminuera considérablement.

En ce sens, l'émergence d'outils tels que Xamarin qui peuvent créer les deux binaires avec un seul code sera un tournant dans le futur développement mobile. Cependant, je pense que ce sera très instructif d'étudier pour que vous puissiez faire la même chose dans les deux cas, alors saisissez cette occasion pour vous mettre au défi! !!

Recommended Posts

Comparaison approfondie des implémentations Android et iOS
Comparaison d'Android Handler Looper et de runOnUiThread
Comparaison de l'implémentation de la production qui fait briller les images sur iOS et Android
[Java / Swift] Comparaison de l'interface Java et du protocole Swift
Comparaison des objets JavaScript et des classes Ruby
Chrome59 Comparaison du fonctionnement en mode normal et sans tête
La comparaison d'énumération est ==, et equals est bonne [Java]
Comparaison équivalente de la classe wrapper Java et du type primitif
Développement d'applications iOS: application Timer (5. Implémentation d'alarme et de vibration)
[Java] Comparaison des chaînes de caractères et && et ||
Je vais expliquer la différence entre le développement d'applications Android et le développement d'applications iOS du point de vue des ingénieurs iOS
Définition des constantes Android