2015-01-29 2 views
0

Я работаю над веб-приложением, которое будет анализировать сайт и динамически загружать новости в CardView. На данный момент он работает и делает все необходимое. Но это не совсем то, что я хочу. Вот часть моего кода, чтобы понять, что я имею в виду:AsyncTask показывает ход загрузки и возвращает значение jsoup

public class NewsPage extends ActionBarActivity { 
    List<NewCard> listNC = new ArrayList<NewCard>(); 


    class NewsParser extends AsyncTask<Void,Void,List<NewCard>> { 
     Document doc; 
     List<NewCard> nc = new ArrayList<NewCard>(); 
     ProgressDialog progressDialog; 
     @Override 
     protected void onPreExecute() 
     { 
      // progressDialog= ProgressDialog.show(NewsPage.this, "Parsing the site", "Please wait while the information is loading...", true); 
     }; 

     @Override 
     protected List<NewCard> doInBackground(Void... params) { 
      try { 
//some code skipped 
        nc.add(new NewCard(forHeader.html(), forDesc, URLforImg, forHeader.attr("href"))); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return nc; 
     } 

     protected void onPostExecute(String[] s) { 
     progressDialog.dismiss();//This method is being called out by new <class name>.execute(); 
      //listNC = new ArrayList<NewCard>(nc); 
     } 
    } 

В здесь я извлечении заголовков статей для дальнейшего открытия.

Это мой метод OnCreate():

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_news_page); 
    RecyclerView recList = (RecyclerView) findViewById(R.id.cardList); 
    recList.setHasFixedSize(true); 
    LinearLayoutManager llm = new LinearLayoutManager(this); 
    llm.setOrientation(LinearLayoutManager.VERTICAL); 
    recList.setLayoutManager(llm); 

    try { 
     NewsParser np = new NewsParser(); 
     np.execute(); 
     listNC = np.get(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 


    NewsAdapter na = new NewsAdapter(listNC); 
    size = na.sizes; 
    recList.setAdapter(na); 

Я использую свой адаптер для заполнения карточки с информацией и обрабатывать события OnClick.

Мой вопрос заключается в следующем:

  • Мне нужно, чтобы получить информацию от моего AsyncTask, чтобы создать список карт (в данном случае мне нужно количество карт), и я не конечно, я могу продолжать, не возвращая значения. Но это заставляет мое приложение замораживать и не показывать никакого интерфейса до завершения действия. Как это лучше справиться? Может, мне нужно сделать все по-другому? Как мне загружать заголовки новостей отдельно (не все вместе, но в порядке)? И какой цикл (я не знаю, как правильно его называть) мне нужно , чтобы добавлять новости по мере их загрузки (потому что моя программа не работает, если у нее нет списка перед тем, как делать элементы интерфейса) ?

Я попытался рассказать о каждой детали из своего кода, и если это необходимо, я могу добавить и код адаптера.

ответ

1

Ваш пользовательский интерфейс замерзает, потому что ваш метод get() в блоке try блокирует ожидание на AsyncTask. Это побеждает цель даже при использовании AsyncTask. Вместо этого создайте свой Adapter, прежде чем вы начнете AsyncTask, а затем в onPostExecute() установите для нового адаптера данные для нового результата и вызовите метод адаптера notifyDataSetChanged(). Это приведет к тому, что пользовательский интерфейс подберет изменения.

Будьте осторожны при использовании AsyncTask или любого другого механизма резьбы. Они не знакомы с жизненным циклом, поэтому, если метод onPostExecute() имеет какие-либо сильные ссылки на Activity или его внутренние поля членов и пытается напрямую их использовать, он может работать в исключениях состояний.

+0

Благодарим за ответ. Я попробовал то, что вы предложили, но я не уверен, что сделал это, поскольку это нужно сделать. http://pastebin.com/nUcbz2j9 Это все еще не сработает для меня. Я думаю, что я испортил порядок действий. Не могли бы вы указать на мою ошибку, пожалуйста? – Vendetta8247

+0

Это потому, что 'onPostExecute()' создает новый объект-адаптер и вызывает на нем 'notifyDataSetChanged()', а не передает новый объект List для существующего адаптера. Я предлагаю переработать ваш 'doInBackground()', чтобы он возвращал новый объект «Список» с контентом. Затем в 'onPostExecute()' отправьте этот новый список в ваш существующий 'Adapter' (создайте собственный метод' swapData() 'или что-то подобное.) После того, как новые данные передаются адаптеру, вы можете вызвать' notify ... '. Вы можете найти эту статью полезной для понимания 'AsyncTask': http://po.st/Cei3m2 –

Смежные вопросы