Ocorreu um erro ao executar meu projeto Android para RssReader.
Código:
URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();
E mostra o erro abaixo:
android.os.NetworkOnMainThreadException
Como posso corrigir esse problema?
java
android
android-networking
networkonmainthread
bejoy george
fonte
fonte
Respostas:
Essa exceção é lançada quando um aplicativo tenta executar uma operação de rede em seu encadeamento principal. Execute seu código em
AsyncTask
:Como executar a tarefa:
No
MainActivity.java
arquivo você pode adicionar esta linha dentro do seuoncreate()
métodoNão se esqueça de adicionar isso ao
AndroidManifest.xml
arquivo:fonte
AsyncTask
e cuida de uma alteração na configuração.Você quase sempre deve executar operações de rede em um thread ou como uma tarefa assíncrona.
Mas é possível remover essa restrição e você substitui o comportamento padrão, se estiver disposto a aceitar as consequências.
Adicionar:
Em sua classe,
e
ADICIONE essa permissão no arquivo manifest.xml do Android:
Consequências:
Seu aplicativo (em áreas de conexão irregular à Internet) fica sem resposta e trava, o usuário percebe lentidão e precisa fazer uma matança forçada, e você corre o risco de o gerente de atividades matar o aplicativo e dizer ao usuário que o aplicativo parou.
O Android tem algumas boas dicas sobre boas práticas de programação para projetar a capacidade de resposta: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
fonte
doInBackground
declaração, 2 colchetes e uma chamada paraexecute()
). Por outro lado, mesmo uma única busca de um site, como você menciona, traz um atraso significativo na capacidade de resposta da interface do usuário. Não seja preguiçoso.Resolvi esse problema usando um novo
Thread
.fonte
A resposta aceita tem algumas desvantagens significativas. Não é aconselhável usar o AsyncTask para redes, a menos que você realmente saiba o que está fazendo. Algumas das desvantagens incluem:
executeOnExecutor
método sobrecarregado e forneça um executor alternativo). O código que funciona bem quando executado em série no ICS pode ser interrompido quando executado simultaneamente no Gingerbread, digamos se você tiver dependências inadvertidas da ordem de execução.Se você deseja evitar vazamentos de memória de curto prazo, ter características de execução bem definidas em todas as plataformas e ter uma base para criar um gerenciamento de rede realmente robusto, convém considerar:
Service
ouIntentService
, talvez com aPendingIntent
para retornar o resultado através doonActivityResult
método da atividade .Abordagem IntentService
Desvantagens:
AsyncTask
, embora não tanto quanto você imaginaIntentService
por umaService
implementação equivalente , talvez como esta .Parte superior:
onActivityResult
métodoAsyncTask
em umActivity
, mas se o contexto do usuário sair do aplicativo para atender uma ligação, o sistema poderá encerrá-lo antes que o upload seja concluído. É menos provável que mate um aplicativo com um ativoService
.IntentService
(como a que eu vinculei acima), poderá controlar o nível de simultaneidade viaExecutor
.Resumo de implementação
Você pode implementar um
IntentService
para executar downloads em um único thread em segundo plano com bastante facilidade.Etapa 1: Crie um
IntentService
para executar o download. Você pode dizer o que fazer o download viaIntent
extra e passá-loPendingIntent
para usar para retornar o resultado paraActivity
:Etapa 2: registre o serviço no manifesto:
Etapa 3: Invoque o serviço da Atividade, passando um objeto PendingResult que o Serviço usará para retornar o resultado:
Etapa 4: manipular o resultado em onActivityResult:
Um projeto do Github que contém um projeto completo do Android-Studio / Gradle está disponível aqui .
fonte
IllustrativeRSS
? E se você não estiver trabalhando com coisas de RSS?AsyncTask
. O erro foi feito para impedir que os desenvolvedores atrasassem a interface do usuário, não necessariamente os levou a arriscar a segurança com várias intenções / serviços.Você não pode executar E / S de rede no thread da interface do usuário no Honeycomb . Tecnicamente, isso é possível nas versões anteriores do Android, mas é uma péssima idéia, pois fará com que o aplicativo pare de responder e pode resultar no sistema operacional que mata o seu aplicativo por se comportar mal. Você precisará executar um processo em segundo plano ou usar o AsyncTask para executar sua transação de rede em um thread em segundo plano.
Há um artigo sobre o Painless Threading no site do desenvolvedor do Android, que é uma boa introdução a isso e fornecerá uma resposta muito melhor do que a fornecida realisticamente aqui.
fonte
Use Service ou AsyncTask
Veja também a questão Stack Overflow:
android.os.NetworkOnMainThreadException enviando um email do Android
fonte
Execute as ações de rede em outro segmento
E adicione isso ao AndroidManifest.xml
fonte
Você desabilita o modo estrito usando o seguinte código:
Isso não é recomendado : use a
AsyncTask
interface.Código completo para ambos os métodos
fonte
Operações baseadas em rede não podem ser executadas no thread principal. Você precisa executar todas as tarefas baseadas em rede em um thread filho ou implementar o AsyncTask.
É assim que você executa uma tarefa em um thread filho:
fonte
Coloque seu código dentro:
Ou:
fonte
Isso acontece no Android 3.0 e acima. A partir do Android 3.0 e superior, eles restringiram o uso de operações de rede (funções que acessam a Internet) da execução no thread principal / thread da interface do usuário (o que gera seus métodos de criação e continuação na atividade).
Isso é para incentivar o uso de threads separados para operações de rede. Consulte AsyncTask para obter mais detalhes sobre como executar atividades de rede da maneira certa.
fonte
Usar anotações do Android é uma opção. Isso permitirá que você simplesmente execute qualquer método em um thread em segundo plano:
Observe que, embora ofereça benefícios de simplicidade e legibilidade, tem suas desvantagens.
fonte
O erro ocorre devido à execução de operações de execução longa no thread principal. Você pode corrigir facilmente o problema usando AsynTask ou Thread . Você pode fazer o check-out desta biblioteca AsyncHTTPClient para obter um melhor tratamento.
fonte
Você não deve executar nenhuma tarefa demorada no encadeamento principal (encadeamento da UI), como qualquer operação de rede, E / S de arquivo ou operações de banco de dados SQLite. Portanto, para esse tipo de operação, você deve criar um encadeamento de trabalho, mas o problema é que não é possível executar diretamente nenhuma operação relacionada à interface do usuário a partir do encadeamento de trabalho. Para isso, você deve usar
Handler
e passar oMessage
.Para simplificar todas estas coisas, Android fornece várias maneiras, como
AsyncTask
,AsyncTaskLoader
,CursorLoader
ouIntentService
. Então você pode usar qualquer um deles de acordo com seus requisitos.fonte
A resposta superior do spektom funciona perfeitamente.
Se você estiver escrevendo o
AsyncTask
inline e não estendendo como uma classe, além disso, se houver necessidade de obter uma respostaAsyncTask
, pode-se usar oget()
método como abaixo.(Do exemplo dele.)
fonte
get()
é uma má idéia ... faz AsyncTask "sync" novamenteIsso é lançado somente para aplicativos direcionados ao SDK do Honeycomb ou superior. Os aplicativos direcionados para as versões anteriores do SDK podem fazer networking em seus encadeamentos de loop de eventos principais.
O erro é o aviso do SDK!
fonte
Para mim foi isso:
O dispositivo em que eu estava testando meu aplicativo era 4.1.2, que é o SDK versão 16!
Verifique se a versão de destino é igual à sua Biblioteca de destino do Android. Se você não souber qual é a sua biblioteca de destino, clique com o botão direito do mouse em Projeto -> Caminho da Construção -> Android , e deve ser a que está marcada.
Além disso, como outros já mencionaram, inclua as permissões corretas para acessar a Internet:
fonte
NetworkOnMainThreadException
é o Guardian que está lhe dizendo: não atire no seu próprio pé ... sua solução é: vamos voltar ao passado quando não havia Guardian - agora eu posso atirar no meu pé livrementeUse isso em sua atividade
fonte
Apenas para esclarecer algo explicitamente:
O thread principal é basicamente o thread da interface do usuário.
Dizer que você não pode realizar operações de rede no encadeamento principal significa que não pode realizar operações de rede no encadeamento da interface do usuário, o que significa que não é possível realizar operações de rede em um
*runOnUiThread(new Runnable() { ... }*
bloco dentro de outro encadeamento.(Eu tive um longo momento de coçar a cabeça tentando descobrir por que estava recebendo esse erro em outro lugar que não o meu thread principal. Foi por isso; esse thread ajudou; e espero que esse comentário ajude outra pessoa.)
fonte
Essa exceção ocorre devido a qualquer tarefa pesada executada no encadeamento principal, se essa tarefa em execução demorar muito tempo .
Para evitar isso, podemos lidar com isso usando threads ou executores
fonte
Já existem muitas ótimas respostas para essa pergunta, mas muitas grandes bibliotecas surgiram desde que essas respostas foram postadas. Este é um tipo de guia para iniciantes.
Vou cobrir vários casos de uso para executar operações de rede e uma ou duas soluções para cada uma.
ReST sobre HTTP
Tipicamente Json, pode ser XML ou outra coisa
Acesso completo à API
Digamos que você esteja escrevendo um aplicativo que permita aos usuários acompanhar os preços das ações, taxas de juros e taxas de câmbio. Você encontra uma API Json que se parece com isso:
Retrofit from Square
Essa é uma excelente opção para uma API com vários pontos de extremidade e permite declarar os pontos de extremidade do ReST em vez de precisar codificá-los individualmente, como acontece com outras bibliotecas como ion ou Volley. (site: http://square.github.io/retrofit/ )
Como você o usa com a API de finanças?
build.gradle
Adicione estas linhas ao seu buid.gradle no nível do módulo:
FinancesApi.java
FinancesApiBuilder
Fragmento de fragmento
Se sua API exigir que uma chave de API ou outro cabeçalho como um token de usuário etc. seja enviado, o Retrofit facilita isso (consulte esta resposta incrível para obter detalhes: https://stackoverflow.com/a/42899766/1024412 ).
Acesso único à API do ReST
Digamos que você esteja criando um aplicativo "clima ameno" que pesquise a localização do GPS do usuário e verifique a temperatura atual nessa área e informe o clima. Esse tipo de aplicativo não precisa declarar pontos de extremidade da API; ele só precisa acessar um ponto de extremidade da API.
Íon
Esta é uma ótima biblioteca para esse tipo de acesso.
Leia a excelente resposta de msysmilu ( https://stackoverflow.com/a/28559884/1024412 )
Carregar imagens via HTTP
Vôlei
O Volley também pode ser usado para APIs ReST, mas devido à configuração mais complicada necessária, eu prefiro usar o Retrofit from Square como acima ( http://square.github.io/retrofit/ )
Digamos que você esteja criando um aplicativo de rede social e deseje carregar fotos de perfil de amigos.
build.gradle
Adicione esta linha ao seu nível de módulo buid.gradle:
ImageFetch.java
O Volley requer mais configuração que o Retrofit. Você precisará criar uma classe como esta para configurar um RequestQueue, um ImageLoader e um ImageCache, mas não é tão ruim assim:
user_view_dialog.xml
Adicione o seguinte ao arquivo xml de layout para adicionar uma imagem:
UserViewDialog.java
Adicione o seguinte código ao método onCreate (Fragment, Activity) ou ao construtor (Dialog):
Picasso
Outra excelente biblioteca da Square. Consulte o site para alguns ótimos exemplos: http://square.github.io/picasso/
fonte
Em palavras simples,
NÃO TRABALHE EM REDE NA LINHA DA UI
Por exemplo, se você fizer uma solicitação HTTP, essa é uma ação de rede.
Solução:
Caminho:
Coloque todos os seus trabalhos dentro
run()
método de nova discussãodoInBackground()
método da classe AsyncTask.Mas:
Quando você obtém algo da resposta de rede e deseja mostrá-lo em sua exibição (como exibir mensagem de resposta no TextView), é necessário retornar ao thread da interface do usuário .
Se você não fizer isso, você receberá
ViewRootImpl$CalledFromWrongThreadException
.Como?
onPostExecute()
métodorunOnUiThread()
método e atualize a exibição dentro dorun()
método.fonte
Você pode mover uma parte do seu código para outro thread para descarregar
main thread
e evitar ANR , NetworkOnMainThreadException , IllegalStateException (por exemplo, não é possível acessar o banco de dados no thread principal, pois pode bloquear a interface do usuário por um longo período de tempo).Existem algumas abordagens que você deve escolher depende da situação
Thread Java ou Android HandlerThread
AsyncTask
Implementação do conjunto de encadeamentos ThreadPoolExecutor , ScheduledThreadPoolExecutor ...
FutureTask
AsyncTaskLoaders
IntentService
JobScheduler
RxJava
Corotinas (Kotlin)
Leia mais aqui , aqui , aqui , aqui
fonte
Embora acima haja um enorme pool de soluções, ninguém mencionou
com.koushikdutta.ion
: https://github.com/koush/ionTambém é assíncrono e muito simples de usar:
fonte
As soluções novas
Thread
e AsyncTask já foram explicadas.AsyncTask
idealmente deve ser usado para operações curtas. NormalThread
não é preferível para Android.Dê uma olhada na solução alternativa usando HandlerThread e Handler
HandlerThread
Manipulador:
Solução:
Crio
HandlerThread
Ligue
start()
paraHandlerThread
Crie
Handler
obtendoLooper
deHanlerThread
Incorpore o código relacionado à operação de rede no
Runnable
objetoEnviar
Runnable
tarefa paraHandler
Exemplo de trecho de código, que endereço
NetworkOnMainThreadException
Prós de usar esta abordagem:
Thread/AsyncTask
para cada operação de rede é caro. OThread/AsyncTask
será destruído e recriado para as próximas operações de rede. Mas comHandler
e com aHandlerThread
abordagem, você pode enviar muitas operações de rede (como tarefas executáveis) para uma únicaHandlerThread
usandoHandler
.fonte
RxAndroid
é outra alternativa melhor para esse problema e evita aborrecimentos na criação de threads e na publicação de resultados no thread da interface do usuário do Android. Nós apenas precisamos especificar threads nos quais as tarefas precisam ser executadas e tudo é tratado internamente., Especificando
(Schedulers.io())
, RxAndroid será executadogetFavoriteMusicShows()
em um segmento diferente.Ao usar
AndroidSchedulers.mainThread()
, queremos observar este Observável no thread da interface do usuário, ou seja, queremos que nossoonNext()
retorno de chamada seja chamado no thread da interface do usuáriofonte
O thread principal é o thread da interface do usuário e você não pode executar uma operação no thread principal que possa bloquear a interação do usuário. Você pode resolver isso de duas maneiras:
Forçar a executar a tarefa no thread principal como este
Ou crie um manipulador simples e atualize o segmento principal, se desejar.
E para parar o thread, use:
Para obter mais informações, consulte: Rosqueamento indolor
fonte
Isso funciona. Apenas simplificou a resposta do Dr. Luiji.
fonte
No Android, as operações de rede não podem ser executadas no thread principal. Você pode usar o Thread, AsyncTask (tarefas de execução curta), Serviço (tarefas de execução longa) para executar operações de rede.
fonte
O acesso a recursos de rede a partir do thread principal (UI) causa essa exceção. Use um thread separado ou o AsyncTask para acessar um recurso de rede para evitar esse problema.
fonte