У меня есть recyclerView, который загружает и показывает элементы, которые мне нужны, но есть задержка (когда приложение получает новости xml из Интернета и анализирует их), и я хочу, чтобы появился индикатор progressBar, чтобы указать пользователя . Индикатор выполнения есть, но он никогда не появляется.
Вот мой код:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, SearchView.OnQueryTextListener {
private ArrayList<NewsItem> newsItems;
private ProgressBar updateProgressBar;
private RecyclerView newsItemsRecyclerView;
private NewsAdapter newsAdapter;
private SearchView searchView;
private NewsAddressProvider newsAddressProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hookUpScreenViews();
//making the list ready
newsItems = new ArrayList<>();
//getting the news
newsAddressProvider = new NewsAddressProvider();
getTheNews(newsAddressProvider.getGeneral());
//setting up the search view
searchView.setOnQueryTextListener(this);
}
private void getTheNews(ArrayList<String> addresses) {
for (String address : addresses) {
StringRequest stringRequest = new StringRequest(address, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
NewsXMLParser newsXMLParser = new NewsXMLParser(response);
newsXMLParser.parseNewsXml();
newsItems.addAll(newsXMLParser.getNewsItems());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(this).add(stringRequest);
}
updateRecyclerView(newsItems);
}
private void hookUpScreenViews() {
//setting the progressBar
updateProgressBar = findViewById(R.id.updateProgressBar);
newsItemsRecyclerView = findViewById(R.id.newsItemsRecyclerView);
searchView = findViewById(R.id.main_news_search_view);
}
private void updateRecyclerView(ArrayList<NewsItem> newsList) {
if (newsList != null) {
updateProgressBar.setVisibility(View.INVISIBLE);
}
newsAdapter = new NewsAdapter(newsList, this);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
newsItemsRecyclerView.setLayoutManager(layoutManager);
newsItemsRecyclerView.setAdapter(newsAdapter);
newsAdapter.notifyDataSetChanged();
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (newsAdapter != null) {
newsAdapter.getFilter().filter(newText);
}
return true;
}
}
Я тоже пробовал
if (newsList != null) {
updateProgressBar.setVisibility(View.GONE);
}
и этот код:
if (newsList != null && newsList.size()>0) {
updateProgressBar.setVisibility(View.INVISIBLE);
}
Я также использовал .GONE со вторым подходом, но на этот раз ProgreesBar никогда не работает, он просто остается там и вращается повсюду, и когда я пробую Log.d, он говорит, что список новостей пуст !, хотя явно есть значения в нем, и recyclerView их показывает.
вместо .size() я тоже проверял с .isEmpty(), но результат все тот же!
и вот xml для индикатора выполнения:
<?xml version = "1.0" encoding = "utf-8"?>
<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
app:layout_behavior = "@string/appbar_scrolling_view_behavior"
tools:context = ".activities.MainActivity">
<android.support.v7.widget.RecyclerView
android:background = "@color/transparent"
android:padding = "5dp"
android:id = "@+id/newsItemsRecyclerView"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:layout_above = "@+id/mobileBanner"
android:layout_alignParentLeft = "true"
android:layout_alignParentStart = "true"
android:layout_alignParentTop = "true"
android:divider = "@color/transparent"/>
<ProgressBar
android:id = "@+id/updateProgressBar"
style = "?android:attr/progressBarStyle"
android:layout_width = "100dp"
android:layout_height = "100dp"
android:layout_centerInParent = "true"
android:layout_gravity = "top|center_horizontal"/>
</RelativeLayout>
Ваш метод updateRecyclerView был вызван в MainThead и сразу же был выполнен.
Поместите свой метод updateRecyclerView в onResponse и onErrorResponse
но onResponse находится внутри цикла for.
Простой глобальный счетчик проверяет, все ли ваши адреса проанализированы.
Проблема в том, что вы в основном вызываете updateProgressBar.setVisibility(View.INVISIBLE); косвенно из onCreate().
Запрос Volley является асинхронным, поэтому onResponse() вызывается после завершения запроса.
В основном ваш код работает следующим образом: сначала из onCreate() вы вызываете getTheNews(), который почти мгновенно проходит цикл for (Volley асинхронный). Затем updateRecyclerView(), затем updateProgressBar.setVisibility(View.INVISIBLE);
Поскольку это происходит очень быстро, вы никогда не увидите ProggessBar.
Обновлено:
Добавьте переменную класса для счетчика:
private int addressCounter = 0;
Теперь измените свой метод getTheNews() следующим образом:
private void getTheNews(ArrayList<String> addresses) {
for (String address : addresses) {
StringRequest stringRequest = new StringRequest(address, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
NewsXMLParser newsXMLParser = new NewsXMLParser(response);
newsXMLParser.parseNewsXml();
newsItems.addAll(newsXMLParser.getNewsItems());
newsAdapter.notifyDataSetChanged();
if (addessCounter >= address.size()){
updateProgressBar.setVisibility(View.INVISIBLE);
}
//Increment the counter
addressCounter++;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (addessCounter >= address.size()){
updateProgressBar.setVisibility(View.INVISIBLE);
}
//increment the counter here, too!
addressCounter++;
}
});
Volley.newRequestQueue(this).add(stringRequest);
}
}
Вы также можете рассмотреть:
Если вы собираетесь использовать hookUpScreenViews() для инициализации ваших представлений, почему бы не добавить searchView.setOnQueryTextListener(this);? Вы также можете добавить код для настройки RecyclerView, потому что его нужно вызвать только один раз.
private void hookUpScreenViews() {
//setting the progressBar
updateProgressBar = findViewById(R.id.updateProgressBar);
newsItemsRecyclerView = findViewById(R.id.newsItemsRecyclerView);
searchView = findViewById(R.id.main_news_search_view);
searchView.setOnQueryTextListener(this);
newsAdapter = new NewsAdapter(newsList, this);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
newsItemsRecyclerView.setLayoutManager(layoutManager);
newsItemsRecyclerView.setAdapter(newsAdapter);
}
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я не пробовал этот код, поэтому вам может потребоваться его немного подправить.
Обновлено: это рабочий код:
public void onResponse(String response) {
addressCounter++;
NewsXMLParser newsXMLParser = new NewsXMLParser(response);
newsXMLParser.parseNewsXml();
newsItems.addAll(newsXMLParser.getNewsItems());
if (addressCounter>=addresses.size()){
updateRecyclerView(newsItems);
}
}
ну, точный код не работает, но после небольшой настройки, как вы сказали, он начинает работать! Спасибо
вы можете опубликовать свой xml для индикатора выполнения?