Błąd podczas rozszerzania klasy

188

Próbuję utworzyć niestandardowy widok, GhostSurfaceCameraViewktóry się rozszerza SurfaceView. Oto mój plik definicji klasy

GhostSurfaceCameraView.java:

public class GhostSurfaceCameraView extends SurfaceView implements SurfaceHolder.Callback {
    SurfaceHolder mHolder;
    Camera mCamera;

    GhostSurfaceCameraView(Context context) {
        super(context);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where to draw.
        mCamera = Camera.open();
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
            // TODO: add more exception handling logic here
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }   

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(w, h);
        parameters.set("orientation", "portrait");
        // parameters.setRotation(90); // API 5+
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }
}

A to jest w moim ghostviewscreen.xml:

<com.alpenglow.androcap.GhostSurfaceCameraView android:id="@+id/ghostview_cameraview"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"/>

Teraz w działalności, którą wykonałem:

protected void onCreate(Bundle savedInstanceState) {
    try {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ghostviewscreen);
    }
}

Kiedy setContentView()zostanie wywołany, zostanie zgłoszony wyjątek:

Binary XML file 09-17 22:47:01.958: ERROR/ERROR(337):
ERROR IN CODE:
android.view.InflateException: Binary
XML file line #14: Error inflating
class
com.alpenglow.androcap.GhostSurfaceCameraView

Czy ktoś może mi powiedzieć, dlaczego otrzymuję ten błąd? Dzięki.

ekscentryczny
źródło

Odpowiedzi:

369

Myślę, że zrozumiałem, dlaczego to nie działa. Dostarczałem konstruktora tylko dla przypadku jednego parametru „kontekst”, podczas gdy powinienem był dostarczyć konstruktor dla przypadku dwóch parametrów „Context, AttributeSet”. Musiałem również przyznać konstruktorowi (om) publiczny dostęp. Oto moja poprawka:

public class GhostSurfaceCameraView extends SurfaceView implements SurfaceHolder.Callback {
        SurfaceHolder mHolder;
        Camera mCamera;

        public GhostSurfaceCameraView(Context context)
        {
            super(context);
            init();
        }
        public GhostSurfaceCameraView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            init();
        }
        public GhostSurfaceCameraView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
ekscentryczny
źródło
4
Czasami najprostsze rzeczy mogą być problemem :) Dobrze wiedzieć, że oba parametry służą do pompowania.
Warpzit,
5
Dziękuję Ci!! Nigdzie w przykładach nie znalazłem żadnej wzmianki o konieczności przeciążenia wszystkich konstruktorów! Zaoszczędziłeś mi godzin (dni?) Czasu.
SMBiggs
1
Wielkie dzięki! Komunikat o błędzie jest dość nieokreślony, co przez chwilę mnie zaskoczyło, powinni uwzględnić przyczynę (brak przeciążenia konstruktora) w swoim komunikacie o błędzie.
AgentKnopf,
1
dzięki za to. czy ktoś wie, czy to się dzieje na całej planszy dla niestandardowych widoków? musisz uwzględnić oba konstruktory, gdy tworzysz niestandardowy widok? (kontekst, a następnie kontekst i atrybuty)
Tim,
2
O, Powinienem to zobaczyć wcześniej! Wiadomość View is not using the 2- **OR** 3-argument View constructorsjest trochę myląca.
Attacktive
45

@Tim - Oba konstruktory nie są wymagane, potrzebny jest tylko ViewClassName(Context context, AttributeSet attrs )konstruktor. Przekonałem się o tym w bolesny sposób, po wielu godzinach straconego czasu.

Jestem bardzo nowy w programowaniu dla Androida, ale zgaduję, że może to dlatego, że skoro dodajemy Viewklasę niestandardową w pliku XML, ustawiamy jej kilka atrybutów w pliku XML, co wymaga do przetworzenia w czasie tworzenia instancji. Ktoś o wiele bardziej kompetentny niż ja będzie mógł jednak rzucić jaśniejsze światło na tę sprawę.

KVNam
źródło
Ma to sens, mój niestandardowy TextView zawsze jest konstruowany z ViewClassName (kontekst kontekstowy, atrybuty AttributeSet), gdy definiuję dla niego atrybuty w xml. Jeśli utworzę jego wystąpienie bez definiowania w pliku xml, zwykły konstruktor zostanie wywołany tylko z kontekstem ViewClassName (kontekst kontekstowy). Zastanawiałem się, co robi inny konstruktor i zgodnie z tym: stackoverflow.com/a/4022916/1505341 answer, ma służyć do ustawienia bazowego stylu widoku.
Kerem
19

Inną możliwą przyczyną komunikatu „Błąd zawyżania klasy” może być błędna pisownia pełnej nazwy pakietu, jeśli jest ona określona w formacie XML:

<com.alpenglow.androcap.GhostSurfaceCameraView android:id="@+id/ghostview_cameraview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

Otwarcie pliku XML układu w edytorze Eclipse XML powinno uwydatnić ten problem.

rmtheis
źródło
2
To była rzeczywiście poprawka dla mojej aplikacji. com.zerokol.views.joystickview Został com.zerokol.views.JoystickView I zadziałało!
Andy
prawdziwe. Sprawdź dokładnie pisownię lub spróbuj pracować z intencjami dostarczonymi przez twoje IDE, po prostu zacznij od wpisania nazwy pakietu, a wszystkie dostępne klasy zostaną pokazane pod intencjami.
Khay
to był mój przypadek.
Banee Ishaque K
2

Ważne jest, aby napisać pełną ścieżkę klasy w pliku xml. Otrzymałem komunikat „Błąd zawyżania klasy”, gdy była zapisana tylko nazwa podklasy.

Mykoła
źródło
Jest to bardzo podobne do tego, co sugeruje @rmtheis. Prawdopodobnie lepiej skomentować jego odpowiedź lub nawet edytować ją z dodatkowymi informacjami.
Ilia Barahovski
1

Ten błąd nęka mnie od kilku godzin. Okazało się, że dodałem niestandardową bibliotekę widoku jako moduł w Android Studio, ale zaniedbałem dodanie jej jako zależności w aplikacji build.gradle.

dependencies {
    ...
    compile project(':gifview')
}
Ionoclast Brigham
źródło
1

fwiw , otrzymałem ten błąd z powodu jakiejś niestandardowej inicjalizacji w konstruktorze, próbującej uzyskać dostęp do obiektu zerowego.

Tom Howard
źródło
0

Miałem ten sam problem podczas rozszerzania TextEdit. Dla mnie błędem było to, że nie dodałem „publicznego” do konstruktora. W moim przypadku działa, nawet jeśli zdefiniuję tylko jeden konstruktor, ten z argumentami Contexti AttributeSet. Okablowana rzecz polega na tym, że błąd ujawnia się tylko wtedy, gdy buduję APK (podpalony lub nie) i przenoszę go na urządzenia. Gdy aplikacja jest uruchamiana za pośrednictwem AndroidStudio -> RunApp na urządzeniu podłączonym przez USB, aplikacja działa.

Nicola Mingotti
źródło
0

w moim przypadku dodałem taki cykliczny zasób:

<drawable name="above_shadow">@drawable/above_shadow</drawable>

następnie zmieniono na

<drawable name="some_name">@drawable/other_name</drawable>

i zadziałało

Evgenii Vorobei
źródło
0

W moim przypadku skopiowałem swoją klasę z innego miejsca i nie zauważyłem od razu, że to abstractzajęcia. Nie możesz nadmuchać klas abstrakcyjnych.

Izajasz J.
źródło
0

Należy tutaj zrozumieć, że:

Konstruktor ViewClassName(Context context, AttributeSet attrs )jest wywoływany podczas wypełniania customView za pomocą XML. Widzisz, że nie używasz słowa kluczowego new do utworzenia instancji obiektu, czyli nie robisz tego new GhostSurfaceCameraView(). Robiąc to , wywołujesz pierwszy konstruktor tj public View (Context context).

Natomiast podczas zawyżania widoku z XML, tj. Podczas używania setContentView(R.layout.ghostviewscreen);lub używania findViewById, ty NIE, nie ty! , system Android wywołuje ViewClassName(Context context, AttributeSet attrs )konstruktora.

Jest to jasne podczas czytania dokumentacji: „Konstruktor, który jest wywoływany podczas zawyżania widoku z XML”. Zobacz: https://developer.android.com/reference/android/view/View.html#View(android.content.Context,%20android.util.AttributeSet)

Dlatego nigdy nie zapominaj o podstawowym polimorfizmie i nigdy nie zapomnij o przeczytaniu dokumentacji. Oszczędza mnóstwo bólu głowy.

kush
źródło