Итак, я запускаю AsyncTask, когда начинается действие. Я пытаюсь реализовать бесконечный список. Когда пользователь прокручивает список до конца, AsyncTask должен начать приносить новые данные. Между тем, если пользователь прокручивает вверх и снова прокручивает вниз, это то место, где я получаю ошибку.
Вот код, который я пробовал:
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SearchView.OnQueryTextListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
public class CaseListingActivity extends ActionBarActivity {
ListView mListViewCase;
ArrayList<CaseDetails> mArrayList;
CaseListAdapter mCaseListAdapter;
View mView;
CaseListingTask mCaseListingTask;
int preLast;
int currentPage = 1;
public static final String URL = "http://xxxxxx.xxxxxxx/DC.svc/rest/GetSubject?PageNo=";
public static final String GET_SUBJECT_RESULT = "GetSubjectResult";
public static final String ID = "Id";
public static final String SUB = "Sub";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_case_listing);
mArrayList = new ArrayList<CaseDetails>();
mCaseListAdapter = new CaseListAdapter(this, mArrayList);
mCaseListingTask = new CaseListingTask();
mView = ((LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.listview_footer, null, false);
mListViewCase = (ListView) findViewById(R.id.listViewCaseListing);
mListViewCase.addFooterView(mView);
mListViewCase.setAdapter(mCaseListAdapter);
mListViewCase.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
// if (scrollState == SCROLL_STATE_IDLE) {
// if (mListViewCase.getLastVisiblePosition() >= mListViewCase
// .getCount() - 1 - 1) {
//
// // if (mCaseListingTask.getStatus() !=
// AsyncTask.Status.RUNNING) {
// //
// // }
// if (mCaseListingTask.getStatus() == AsyncTask.Status.RUNNING)
// {
// // Do Something?
// } else {
// currentPage++;
// // load more list items:
// mCaseListingTask.execute(URL + currentPage);
// }
// }
// }
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
switch (view.getId()) {
case R.id.listViewCaseListing:
// Make your calculation stuff here. You have all your
// needed info from the parameters of this function.
// Sample calculation to determine if the last
// item is fully visible.
final int lastItem = firstVisibleItem + visibleItemCount;
if (lastItem == totalItemCount) {
// if (preLast != lastItem) { // to avoid multiple calls
// // for last item
// Log.d("Last", "Last");
// preLast = lastItem;
if (mCaseListingTask.getStatus() == AsyncTask.Status.FINISHED) {
currentPage++;
// load more list items:
mCaseListingTask.execute(URL + currentPage);
}
// }
}
}
}
});
mListViewCase.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
Toast.makeText(getBaseContext(),
arg0.getItemAtPosition(arg2).toString(),
Toast.LENGTH_SHORT).show();
}
});
new CaseListingTask().execute(URL + currentPage);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat
.getActionView(searchItem);
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onQueryTextChange(String arg0) {
// TODO Auto-generated method stub
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
public class CaseListingTask extends AsyncTask<String, Void, String> {
ProgressDialog mProgressDialog;
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String result = "";
for (String string : params) {
result = new JSONParser().getJSONFromUrl(string);
}
return result;
}
/*
* (non-Javadoc)
*
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
try {
JSONObject mJsonObject = new JSONObject(result);
JSONArray mJsonArray = mJsonObject
.getJSONArray(GET_SUBJECT_RESULT);
for (int i = 0; i < mJsonArray.length(); i++) {
JSONObject c = mJsonArray.getJSONObject(i);
mArrayList.add(new CaseDetails(c.getInt(ID), c
.getString(SUB)));
}
mCaseListAdapter.notifyDataSetChanged();
mListViewCase.removeFooterView(mView);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* (non-Javadoc)
*
* @see android.os.AsyncTask#onPreExecute()
*/
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
// mProgressDialog = ProgressDialog.show(CaseListingActivity.this,
// "Please Wait...", "Loading...", true, false);
mListViewCase.addFooterView(mView, null, false);
}
}
}
Если вам нужна дополнительная информация, спросите об этом. Спасибо.
1 ответ
Проблема проста: вы можете выполнить каждый AsyncTask
только один раз. Из документации AsyncTask :
Для этого класса необходимо соблюдать несколько правил потоковой передачи . чтобы работать правильно:
- Класс AsyncTask должен быть загружен в поток пользовательского интерфейса. Это делается автоматически с JELLY_BEAN.
- Экземпляр задачи должен быть создан в потоке пользовательского интерфейса.
- execute (Params ...) должен вызываться в потоке пользовательского интерфейса.
- Не вызывайте onPreExecute (), onPostExecute (Result), doInBackground (Params ...), onProgressUpdate (Progress ...) вручную.
- Задача может быть выполнена только один раз (при второй попытке выполнения будет выдано исключение) .
Вы создаете новый экземпляр CaseListingTask
в onCreate()
и пытаетесь повторно использовать этот же экземпляр в своем OnScrollListener
. Что вам нужно сделать, так это создавать новый экземпляр CaseListingTask
каждый раз, когда вы хотите его запустить.
Итак, чтобы подвести итог, замените это:
if (mCaseListingTask.getStatus() == AsyncTask.Status.FINISHED) {
currentPage++;
// load more list items:
mCaseListingTask.execute(URL + currentPage);
}
С этим:
if (mCaseListingTask.getStatus() == AsyncTask.Status.FINISHED) {
currentPage++;
mCaseListingTask = new CaseListingTask();
mCaseListingTask.execute(URL + currentPage);
}
mCaseListingTask = new CaseListingTask();
. Не могли бы вы объяснить это.
Threading Rules
, который вы упомянули. Еще раз спасибо.
Похожие вопросы
Новые вопросы
android
Android — это мобильная операционная система Google, используемая для программирования или разработки цифровых устройств (смартфонов, планшетов, автомобилей, телевизоров, одежды, очков, IoT). Для тем, связанных с Android, используйте теги, специфичные для Android, такие как android-intent, android-activity, android-adapter и т. д. Для вопросов, отличных от разработки или программирования, но связанных с Android framework, используйте эту ссылку: https://android .stackexchange.com.