2016-06-14 4 views
3

Ich möchte mit meinem Code ermitteln, welcher Objekttyp automatisch benötigt wird.Ermitteln des erforderlichen Objekttyps aus nicht initialisiertem Objekt

Hintergrund:

Der Code anhängen ein Widget häufig ist wie folgt:

TextView textView = (TextView) findViewById(R.id.textView); 

Ich möchte dann prüfen, ob Textview richtig, um Fehler zu vermeiden gefunden wurde. Dazu verwende ich eine benutzerdefinierte (AttachWidgetException) Ausnahme:

if(textView == null) throw new AttachWidgetException(name); 

Idee:

Anstatt diese beiden Zeilen für jedes Widget in meinem Code (DRY) wiederholen zu müssen, entschied ich mich um eine Funktion zu vereinfachen. Ich fälschlicherweise angenommen, könnte ich dies tun:

public View attachWidget(View view, int resID, String name) throws AttachWidgetException { 
    view = (view.getClass) findViewById(resID); 

    if(view == null) throw new AttachWidgetException(name); 
    return view; 
} 

Genannt aus einem Block Versuchen von:

TextView textView = attachWidget(textView, R.id.textView, "textView"); 

Problem:

Aber dies aus zwei Gründen nicht funktioniert . Das Objekt des Aufrufers erwartet eine TextView, keine View. Ich denke, der andere Grund ist Ansicht noch instanziiert werden soll, und deshalb, wie berichtet wird:

java.lang.Class <capture<? extends android.view.View> 

..., die nicht eine Erweiterung der Ansicht ist. Um dies zu beheben, muss ich die Linie in attachWidget ändern:

view = findViewById(resID); 

... und die anrufende Leitung zu:

TextView textView = (TextView) attachWidget(textView, R.id.textView, "textView"); 

..., die der Ansicht Eingabeparameter nutzlos macht. Das können wir an dieser Stelle entfernen.

Frage:

Das ist wirklich nicht so schlimm ist, aber gibt es eine Möglichkeit, dies zu tun, so brauche ich nicht manuell die Besetzung hinzufügen? Kann attachWidget automatisch feststellen, dass es ein TextView zurückgeben muss? Ich bin mir ziemlich sicher, dass ich in die falsche Richtung von möglichen Lösungen gehe. Würden Generika mir hier irgendwie helfen?

Bitte vergib mir, wenn ich in meiner Beschreibung falsche Terminologie verwende. Ich würde mich über jede Code/Terminologie/Methodenkorrektur freuen.

+2

Sieht aus wie das Rad neu zu erfinden - wissen Sie, [Buttermesser] (http: // jakewharton.github.io/butterknife/)? – mjn

+0

@mjn Vielen Dank für Ihre Antwort. Eigentlich möchte ich keine externen Bibliotheken verwenden. Vielleicht hätte ich das in meiner ursprünglichen Frage angeben sollen. Ich war mehr daran interessiert zu lernen, ob Java die entsprechenden Möglichkeiten hätte. Es scheint ein ziemlich einfaches Problem zu sein. Ich muss nur die AttachWidget-Funktion angeben, um sie in einen bekannten Typ zu konvertieren. Renans Antwort ist eigentlich ziemlich nah an dem, was ich brauche. – David

Antwort

1

Sie können view.getClass nicht aufrufen, wenn die Ansicht null ist. Versuchen Sie, dies zu tun:

public <T extends View> T attachWidget(Class<T> type, int resID, String name) throws AttachWidgetException { 
     View view = findViewById(resID); 
     if (view == null) throw new AttachWidgetException(name); 
    try { 
     return type.cast(view); 
    } catch (ClassCastException) { 
     e.printStackTrace(); 
     throw new AttachWidgetException(name); 
    } 
} 

In diesem Fall können Sie rufen wie:

TextView textView = attachWidget(TextView.class, R.id.textView, "textView"); 
+0

Danke für die schnelle Antwort. Ich habe die obere Zeile geändert, um T als Rückgabetyp hinzuzufügen. Mein Compiler beklagt, dass die View-Instanz von T immer wahr ist, wenn sie erreicht wird. Aus diesem Grund wird es nicht kompiliert. Eigentlich wird Klasse oder Array statt T erwartet (in diesem Bereich) ist der Grund, warum es nicht kompilieren wird. – David

+0

Okay, das meiste funktioniert jetzt. Danke für die Klasse Bit - ich hatte keine Ahnung davon. Mein Aufrufer sieht jetzt wie folgt aus - textView = attachWidget (TextView.class, R.id.textView, "textView"); - und ich musste den oder, ||, Abschnitt des Codes entfernen, damit er funktioniert. Gibt es da eh das zu beheben? Segment? – David

+0

Anstelle der || Abschnitt, legte ich die Rückkehr type.cast (view) in einem Versuch/catch-Block. Jetzt meldet es, wenn es die Ansicht nicht finden kann oder kann. Dies scheint eine ziemlich saubere Lösung zu sein. Wenn Sie Ihren Code mit meinen Änderungen aktualisieren/Verbesserungen vorschlagen könnten, würde dies Ihre Antwort zu einer guten Wahl für die Akzeptanz machen. – David

Verwandte Themen