Как обрабатывать исключения в Android с помощью throw

Я пытаюсь получить информацию с веб-сайта и отобразить ее в приложении для Android. Второй ответ на вопрос «Какой самый быстрый способ очистить веб-страницу HTML в Android?» предложил использовать BufferedReader. В ответ человек использует класс URL. Я попытался реализовать ответ следующим образом:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import java.net.URL;

public class MainActivity extends AppCompatActivity {
    TextView display = (TextView) findViewById(R.id.textDisplay);

    @Override
    protected void onCreate(Bundle savedInstanceState) throws Exception {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        URL url = new URL("http://stackoverflow.com/questions/2971155");
        BufferedReader reader = null;
        StringBuilder builder = new StringBuilder();
        try {
            reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
            for (String line; (line = reader.readLine()) != null; ) {
                builder.append(line.trim());
            }
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException logOrIgnore) {
                    logOrIgnore.printStackTrace();
                }
            }
        }
        String start = "<div class=\"post-text\"><p>";
        String end = "</p>";
        String part = builder.substring(builder.indexOf(start) + start.length());
        String question = part.substring(0, part.indexOf(end));
        TextView display = (TextView) findViewById(R.id.textDisplay);
        display.setText(question);

    }


}

Я получил эту ошибку:

'onCreate(Bundle)' in 'com.example.myproject.MainActivity' clashes with 
'onCreate(Bundle)' in 'android.appcompat.app.AppCompatActivity';
 overridden method does not throw 'java.lang.Exception'

Что бы вы предложили, чтобы справиться с этим, это умный способ получения данных с веб-сайта? Любая помощь высоко ценится


person MamoRatzo    schedule 04.03.2020    source источник
comment
Добро пожаловать в StackOverflow! Удалите throws Exception, добавьте catch в блок try, вы не можете изменить объявление метода при переопределении. Кроме того, вы получите исключение, потому что вы пытаетесь выполнить сетевой вызов в основном потоке. Используйте библиотеку OkHttp. И да, не пытайтесь анализировать html вручную (у SO есть json API, афаик)   -  person Dima Rostopira    schedule 04.03.2020


Ответы (3)


Измените код следующим образом

    public class MainActivity extends AppCompatActivity {
        TextView display = (TextView) findViewById(R.id.textDisplay);

        @Override
        protected void onCreate(Bundle savedInstanceState) throws Exception {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

try{
            URL url = new URL("http://stackoverflow.com/questions/2971155");
            BufferedReader reader = null;
            StringBuilder builder = new StringBuilder();
            try {
                reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
                for (String line; (line = reader.readLine()) != null; ) {
                    builder.append(line.trim());
                }
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException logOrIgnore) {
                        logOrIgnore.printStackTrace();
                    }
                }
            }
            String start = "<div class=\"post-text\"><p>";
            String end = "</p>";
            String part = builder.substring(builder.indexOf(start) + start.length());
            String question = part.substring(0, part.indexOf(end));
            TextView display = (TextView) findViewById(R.id.textDisplay);
            display.setText(question);
}catch(Exception ex){
Log.e("EEXCCEption","ex.localizedMessage.toString()")

}

        }


    }

и в файле Logger вы можете получить фактическую причину исключения.

person Pawan Soni    schedule 04.03.2020

Во-первых, onCreate() должно быть public, а не protected. Во-вторых, сигнатура onCreate() не вызывает исключения, поэтому вы не можете добавить ее при переопределении. Если вы действительно хотите выбросить, то лучшее, что вы можете сделать, это удалить throws из сигнатуры метода, catch, обернуть его в RuntimeException и повторно выбросить:

try {
  // .. your code
} catch(Exception e){
    throw new RuntimeException(e);
}finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException logOrIgnore) {
                    logOrIgnore.printStackTrace();
                }
            }
        }
person Neeraj    schedule 04.03.2020

Метод onCreate() является частью жизненного цикла Activity, вы просто переопределяете его (примечание @Override), а не пишете собственный, поэтому вы не можете изменять атрибуты, возвращать тип или добавлять/удалять объявления throws

удалить throws Exception из protected void onCreate(Bundle savedInstanceState) throws Exception { - это вызывает ваше исключение

и используйте try{}catch{}, например.

try {
    reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
    for (String line; (line = reader.readLine()) != null; ) {
        builder.append(line.trim());
    }
} catch(Exception e){
    e.printStackTrace();
    //TODO handle exception by own, don't throw outside onCreate, it will break lifecycle
} finally {
    ...

@Neeraj это неправда, на самом деле это единственное, что вы можете изменить - доступность класса (public, protected и т. д.) - но только для «более доступной» версии, то есть с protected на public, но не например. с public по private. кстати. на самом деле super версия этого метода protected, @MamoRatzo не изменил ее, все в порядке

person snachmsm    schedule 04.03.2020