2015-03-15 1 views
2

J'essaie de créer une vue personnalisée Android et je suis confronté à un problème plutôt étrange.Android Custom View: obtenir des références nulles sur tous les membres de la classe dans la méthode onDraw

Chaque membre de données que j'ai défini dans le constructeur (String, Bitmap, ...) devient nul dans la méthode onDraw redéfinie.

Voici le code:

public class SimulationView extends View 
{ 
private static final String TAG = "SIMULATION_VIEW"; 
private String str; 
private Bitmap mField; 

public SimulationView(Context context) { 
    super(context); 
    str = new String("hello"); 
    mField = BitmapFactory.decodeResource(getResources(), R.drawable.field); 
    Log.i(TAG_DEBUG, mField.getHeight() + " " + mField.getWidth()); // displays "1518 900" properly 
    Log.i(TAG, str); // displays "hello" properly 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    Log.i(TAG, str); // throws java.lang.NullPointerException 
    Log.i(TAG, mField.getHeight() + " " + mField.getWidth()); // throws java.lang.NullPointerException (when previous line is commented of course) 
    invalidate(); 
} 

public SimulationView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(context); 
} 

public SimulationView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    init(context); 
} 

private void init(Context context) { 
} 

Voici le stacktrace lorsque la chaîne provoque la NPE:

Process: com.example.simulation_view, PID: 5207 
java.lang.NullPointerException: println needs a message 
     at android.util.Log.println_native(Native Method) 
     at android.util.Log.i(Log.java:160) 
     at com.example.simulation_view.SimulationView.onDraw(SimulationView.java:84) 
     at android.view.View.draw(View.java:15114) 

Et voici le stacktrace lorsque le Bitmap provoque la NPE:

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getHeight()' on a null object reference 
     at com.example.simulation_view.SimulationView.onDraw(SimulationView.java:83) 
     at android.view.View.draw(View.java:15114) 

Qu'est-ce que je fais mal? Toute aide serait grandement appréciée!

un bon jour

+0

Comment créer SimulationView sur le code par constructeur avec Context ou en XML? Ou une fois sur XML et à l'heure dans le code? –

Répondre

3

votre méthode init est vide. Votre code ne fonctionne que si vous instanciez par programmation votre vue personnalisée. Si vous déclarez dans un xml, le bitmap et la chaîne ne sont pas initialisés. Utilisez init pour initialiser, et l'appeler aussi dans le constructeur qui ne prend que le Context en tant que paramètre

private void init(Context context) { 
    str = "hello"; 
    mField = BitmapFactory.decodeResource(getResources(), R.drawable.field); 
} 
+0

Eh bien, cela semble avoir résolu le problème! Merci beaucoup @Blackbelt! Mais je suis curieux, pourquoi l'instanciation faite dans le constructeur n'est-elle pas appliquée? –

+0

lorsque vous déclarez la vue personnalisée en XML, le constructeur appelé est celui avec deux paramètres, 'SimulationView (Contexte contextuel, AttributeSet attrs)', et dans celui-ci vous n'initialisiez pas les objets que vous utilisiez dans l'onDraw – Blackbelt

+0

Ok, mais Dans la conception de mon application, j'instancie ma vue personnalisée en appelant le constructeur à un argument. (Dans MainActivity): 'mSimulationView = new SimulationView (this)' –

0
mField = BitmapFactory.decodeResource(getResources(), R.drawable.field); 

Cette ligne retourne un objet nul et donc lorsque vous essayez d'accéder à la méthode getHeight() il lancera une null exception de pointeur. Essayez de vérifier que les paramètres correspondent à vos attentes. Dans le cas de la méthode onDraw(), vous devez prendre en compte la portée de votre variable globale String str. Il est probable qu'une valeur ne lui soit pas attribuée au moment où elle atteint Log.i(TAG, str); dans votre méthode onDraw(). Pensez plutôt à utiliser des variables locales et à les passer en paramètre aux méthodes nécessaires.

+0

Comme je l'ai commenté dans le constructeur, la fonction Log affiche correctement la hauteur et la largeur de l'image bitmap, prouvant par conséquent que decodeResource ne retourne pas un objet nul. –

+0

Voir la réponse de Blackbelt, je crois qu'il a raison de dire que le problème réside dans votre fonction init. – James

+0

Oui, cela a résolu le problème! Merci pour votre aide si! Je suis vraiment intrigué par la raison pour laquelle les instanciations faites dans mon constructeur ne sont pas appliquées dans le reste du code pendant l'exécution ... –