32 votes

Meilleure pratique: étendre ou remplacer une classe de projet de bibliothèque Android

Nous sommes à l'aide d'un Android Projet de Bibliothèque pour partager des classes de base et des ressources entre les différentes versions (cibles) de notre application Android. Le Android des projets pour chaque objectif spécifique référence de la bibliothèque de Base du projet (derrière les scènes, Eclipse crée et fait référence à un pot de l'référencé projet de bibliothèque).

Primordial des ressources telles que des images et des layouts XML est facile. Ressources les fichiers placés dans le projet cible, comme l'icône de l'application ou d'un fichier XML de mise en page, automatiquement remplacer le noyau de la bibliothèque de ressources avec le même nom lorsque l'application est construite. Cependant, parfois, une classe doit être substituée à activer la cible de comportements spécifiques. Par exemple, l'Amazone de la cible de l'écran préférences ne peut pas contenir un lien vers le Google Play app page, nécessitant un changement dans l'Amazonie du projet preferences.xml et les préférences de l'Activité de la classe.

L'objectif est de réduire la quantité de code en double parmi les projets cibles tout en supprimant autant de cibles particulières de code à partir de la bibliothèque de Base que possible. Nous avons proposé deux approches à mettre en œuvre des logiques propres à différentes cibles:

  1. Écrire la cible des fonctions spécifiques au sein de Base de la bibliothèque de classes et de les utiliser si/commutateur de blocs pour sélectionner le comportement basé sur la référence du produit. Cette approche n'est pas très modulaire et gonfle le Cœur de la bibliothèque de la base de code.
  2. Étendre le particulier de la classe de Base dans une cible de projet et de remplacer la base (Core) des fonctions de classe en tant que de besoin. Puis de conserver une référence à la base de la classe de l'objet dans la bibliothèque de Base et de l'instancier avec une classe étendue de l'objet (à partir de Android projet de bibliothèque - Comment faire pour remplacer une classe?)

Il existe d'autres stratégies pour remplacer ou étendre un Android projet de bibliothèque de classe? Quelles sont les meilleures pratiques pour le partage et l'extension des classes courantes chez Android app cibles?

17voto

PoisoneR Points 501

Projet de bibliothèque est référencé comme une brute projet de dépendance (source mécanisme de base), pas comme la compilation d'un pot de dépendance (compilé en code bibliothèques basées sur le mécanisme).

@yorkw ce n'est pas vrai pour les dernières versions de Plugin ADT pour Eclipse http://developer.android.com/sdk/eclipse-adt.html

À partir de la version 17 journal des modifications

De construction de nouvelles fonctionnalités Ajout de la fonction pour configurer automatiquement POT de dépendances. Tout .les fichiers jar dans le dossier libs sont ajoutés à la configuration de build (similaire à la façon dont l'Ant system works). Aussi, .les fichiers jar requis par les projets de la bibliothèque sont aussi ajoutées automatiquement à des projets qui dépendent de celles de la bibliothèque de projets. (plus d'infos)

Plus d'infos http://tools.android.com/recent/dealingwithdependenciesinandroidprojects

Avant cela, la mise à jour de l'écrasement de l'Activité de la Bibliothèque de projet a été facile, il suffit d'exclure la classe. Maintenant, la bibliothèque est inclus en tant que fichier jar, et on n'est pas à exclure fichier de classe de pot de dépendance.

EDIT:

Ma solution pour overwrete/prolonger l'Activité de la bibliothèque pot:

J'ai créé un simple util classe:

public class ActivityUtil {

private static Class getActivityClass(Class clazz) {

    // Check for extended activity
    String extClassName = clazz.getName() + "Extended";
    try {
        Class extClass = Class.forName(extClassName);
        return extClass;
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        // Extended class is not found return base
        return clazz;
    }
}

public static Intent createIntent(Context context, Class clazz) {
    Class activityClass = getActivityClass(clazz);
    return new Intent(context, activityClass);
}
}

Afin de remplacer une bibliothèque "SampleActivity" classe un projet qui dépend de la bibliothèque, de créer une nouvelle classe avec le nom SampleActivityExtended dans le projet dans le même package et ajouter une nouvelle activité à votre AndroidManifest.xml.

IMPORTANT: toutes les intentions de référencement écrasé les activités devraient être créé par l'util classe de la manière suivante:

Intent intent = ActivityUtil.createIntent(MainActivity.this, SampleActivity.class);
...
startActivity(intent);

4voto

yorkw Points 24676

en coulisses, Eclipse crée et fait référence à un pot de référence de la bibliothèque de projet.

Ce n'est pas tout à fait exact. Projet de bibliothèque est référencé comme une brute projet de dépendance (source mécanisme de base), pas comme la compilation d'un pot de dépendance (compilé en code bibliothèques basées sur le mécanisme). Actuellement SDK Android ne prend pas en charge l'exportation d'un projet de bibliothèque à un fichier JAR. Le projet de bibliothèque doit toujours être compilé/construit indirectement, par référence à la bibliothèque dans l'dépendant de l'application et de la construction de l'application. Quand construire dépendant de projet, la source compilé et des matières premières qui doivent être filtrés/fusionné à partir de la Bibliothèque de projet sont copiés et correctement inclus dans le fichier apk. Notez que Android équipe a commencé la refonte de l'ensemble de la Bibliothèque de la conception du Projet (les déplacer d'un ource mécanisme compilés en code de la bibliothèque mécanisme) depuis r14, comme indiqué dans ce post de blog.

Quelles sont les meilleures pratiques pour le partage et l'extension des classes courantes chez Android app cibles?

La solution donnée par Android est un Projet de Bibliothèque.
La solution donnée par la Java, l'Héritage et le Polymorphisme.
Venir ensemble, les meilleures pratiques de l'OMI est la deuxième option que vous avez mentionné dans la question:

2.Étendre le particulier de la classe de Base dans une cible de projet et de remplacer la base (Core) des fonctions de classe en tant que de besoin. Puis de conserver une référence à la base de la classe de l'objet dans la bibliothèque de Base et de l'instancier avec un objet de classe (à partir d'Android projet de bibliothèque - Comment faire pour remplacer une classe?)

De mon expérience personnelle, j'ai toujours utiliser la version d'Android de la Bibliothèque de Projet (Parfois avec Java Ordinaire de Projet, pour la mise en œuvre/bâtiment common-lib.jar qui ne contient que des POJO) gérer le code commun, par exemple SuperActivity ou SuperService, et s'étend/met en œuvre correcte des classes/interfaces dans le projet dépendant de Polymorphisme.

2voto

Solution basée sur l'Empoisonneuse de la solution et Turbo solution.

public static Class<?> getExtendedClass(Context context, String clsName) {

    // Check for extended activity
    String pkgName = context.getPackageName();
    Logger.log("pkgName", pkgName);
    String extClassName = pkgName + "." + clsName + "Extended";
    Logger.log("extClassName", extClassName);

    try {
        Class<?> extClass = Class.forName(extClassName);
        return extClass;
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        // Extended class is not found return base
        return null;
    }
}

Les avantages de ceci est que

  1. La prolongation de la classe peut être dans le projet de paquet, pas de la bibliothèque dans le package. Grâce au Turbo pour cette partie.

  2. En prenant String comme argument au lieu d'un Class objet, cette méthode est capable d'être utilisé même avec ProGuard. getName() est où le problème est avec ProGuard, qui sera de retour quelque chose comme "un" au lieu du nom de la classe d'origine. Ainsi, dans le solution originale au lieu de chercher ClassExtended, il va chercher les afaites au lieu de cela, quelque chose qui n'existe pas.

1voto

Luminger Points 1810

Que penser de l'utilisation d'un callback approche ici? (D'accord, un rappel est un peu trompeur, mais je n'ai actuellement pas d'autre mot pour cela:

Vous pouvez déclarer une interface dans chaque Activité, qui doit/peut être étendue par l'utilisateur. Cette interface permettra de disposer de méthodes comme l' List<Preference> getPreferences(Activity activity) (pass quels que soient les paramètres dont vous avez besoin ici, je voudrais utiliser un Activity ou d'au moins un Context à futureproof).

Cette approche pourrait vous donner ce que vous voulez, quand j'ai bien compris. Alors que je n'ai pas fait avant et ne savent pas comment d'autres gens à gérer ce que je voudrais lui donner un essai et voir si cela fonctionne.

1voto

Alex Points 448

Pourriez-vous, s'il vous plaît, clarifier ce qui est différent dans Kindle et Android ordinaire? Je pense - ce sont les mêmes. Vous avez besoin de différentes ressources pour Kindle et autres appareils. Utilisez ensuite les ressources appropriées. Par exemple, j'utilise 2 liens pour stocker:

 <string name="appStore">&lt;a href=http://market.android.com/details?id=com.puzzle.jigsaw>Android Market&lt;/a> or &lt;a href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw>Amazon Appstore&lt;/a> &lt;br>http://market.android.com/details?id=com.puzzle.jigsaw &lt;br>href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw</string>
<string name="appStore_amazon">&lt;a href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw>Amazon Appstore&lt;/a> &lt;br>href=http://www.amazon.com/gp/mas/dl/android?p=com.puzzle.jigsaw</string>
 

et utilisez appStore pour tous les produits Amazone et appStore_amazon pour Kindle.

Comment déterminer où vous êtes sur le temps d'exécution - ce serait une autre question à laquelle il a été répondu plusieurs fois ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X