На экране ориентация снова загружает данные с помощью Async Task
Я делаю приложение для Android с шаблоном master/detail. Так что я
- Класс ListActivity, который является FragmentActivity и
- Класс ListFragment, который является Фрагментом
Все работает отлично, но когда я меняю ориентацию экрана, он снова вызывает AsyncTask и перезагружает все данные.
Вот код для класса ListActivity, где я обрабатываю всю логику:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
getActionBar().setTitle("Dnevni horoskop");
if(findViewById(R.id.details_container) != null){
//Tablet
mTwoPane = true;
//Fragment stuff
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
DetailsFragment df = new DetailsFragment();
ft.add(R.id.details_container, df);
ft.commit();
}
pb = (ProgressBar) findViewById(R.id.pb_list);
tvNoConnection = (TextView) findViewById(R.id.tv_no_internet);
ivNoConnection = (ImageView) findViewById(R.id.iv_no_connection);
list = (GridView) findViewById(R.id.gv_list);
if(mTwoPane == true){
list.setNumColumns(1);
//list.setPadding(16,16,16,16);
}
adapter = new CustomListAdapter();
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
pos = position;
if(mTwoPane == false){
Bundle bundle = new Bundle();
bundle.putSerializable("zodiac", zodiacFeed);
Intent i = new Intent(getApplicationContext(), DetailsActivity.class);
i.putExtra("position", position);
i.putExtras(bundle);
startActivity(i);
overridePendingTransition(R.anim.right_in, R.anim.right_out);
}
else if(mTwoPane == true){
DetailsFragment fragment = (DetailsFragment) getSupportFragmentManager().findFragmentById(R.id.details_container);
fragment.setHoroscopeText(zodiacFeed.getItem(position).getText());
fragment.setLargeImage(zodiacFeed.getItem(position).getLargeImage());
fragment.setSign("Dnevni horoskop - "+zodiacFeed.getItem(position).getName());
fragment.setSignDuration(zodiacFeed.getItem(position).getDuration());
// inflate menu from xml
/*if(menu != null){
MenuItem item = menu.findItem(R.id.share);
Toast.makeText(getApplicationContext(), item.getTitle().toString(), Toast.LENGTH_SHORT).show();
}*/
}
}
});
if(!Utils.isConnected(getApplicationContext())){
pb.setVisibility(View.GONE);
tvNoConnection.setVisibility(View.VISIBLE);
ivNoConnection.setVisibility(View.VISIBLE);
}
//Calling AsyncTask to load data
Log.d("TAG", "loading");
HoroscopeAsyncTask task = new HoroscopeAsyncTask(pb);
task.execute();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
}
class CustomListAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
public CustomListAdapter() {
layoutInflater = (LayoutInflater) getBaseContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
// TODO Auto-generated method stub
// Set the total list item count
return names.length;
}
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
// Inflate the item layout and set the views
View listItem = convertView;
int pos = position;
zodiacItem = zodiacList.get(pos);
if (listItem == null && mTwoPane == false) {
listItem = layoutInflater.inflate(R.layout.list_item, null);
}
else if(mTwoPane == true){
listItem = layoutInflater.inflate(R.layout.tablet_list_item, null);
}
// Initialize the views in the layout
ImageView iv = (ImageView) listItem.findViewById(R.id.iv_horoscope);
iv.setScaleType(ScaleType.CENTER_CROP);
TextView tvName = (TextView) listItem.findViewById(R.id.tv_zodiac_name);
TextView tvDuration = (TextView) listItem.findViewById(R.id.tv_duration);
iv.setImageResource(zodiacItem.getImage());
tvName.setText(zodiacItem.getName());
tvDuration.setText(zodiacItem.getDuration());
Animation animation = AnimationUtils.loadAnimation(getBaseContext(), R.anim.push_up);
listItem.startAnimation(animation);
animation = null;
return listItem;
}
}
private void getHoroscope() {
String urlString = "http://balkanandroid.com/download/horoskop/examples/dnevnihoroskop.php";
try {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(urlString);
HttpResponse response = client.execute(post);
resEntity = response.getEntity();
response_str = EntityUtils.toString(resEntity);
if (resEntity != null) {
Log.i("RESPONSE", response_str);
runOnUiThread(new Runnable() {
public void run() {
try {
Log.d("TAG", "Response from server : n "
+ response_str);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
} catch (Exception ex) {
Log.e("TAG", "error: " + ex.getMessage(), ex);
}
}
private class HoroscopeAsyncTask extends AsyncTask<String, Void, Void> {
public HoroscopeAsyncTask(ProgressBar pb1){
pb = pb1;
}
@Override
protected void onPreExecute() {
pb.setVisibility(View.VISIBLE);
super.onPreExecute();
}
@Override
protected Void doInBackground(String... params) {
getHoroscope();
try {
Log.d("TAG", "test u try");
JSONObject jsonObject = new JSONObject(response_str);
JSONArray jsonArray = jsonObject.getJSONArray("horoscope");
for(int i=0;i<jsonArray.length();i++){
Log.d("TAG", "test u for");
JSONObject horoscopeObj = jsonArray.getJSONObject(i);
String horoscopeSign = horoscopeObj.getString("name_sign");
String horoscopeText = horoscopeObj.getString("txt_hrs");
zodiacItem = new ZodiacItem(horoscopeSign, horoscopeText, duration[i], images[i], largeImages[i]);
zodiacList.add(zodiacItem);
zodiacFeed.addItem(zodiacItem);
//Treba u POJO klasu ubaciti sve.
Log.d("TAG", "ZNAK: "+zodiacItem.getName()+" HOROSKOP: "+zodiacItem.getText());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("TAG", "error: " + e.getMessage(), e);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
pb.setVisibility(View.GONE);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
Вот код для класса ListFragment:
public class ListFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
// Retain this fragment across configuration changes.
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_list, container, false);
return view;
}
}
3 ответа
При изменении ориентации вы можете использовать следующее для сохранения задачи:
@Override
public HoroscopeAsyncTask onRetainCustomNonConfigurationInstance() {
return task;
}
тогда в вашем onCreate() вы можете сделать что-то вроде этого:
task = (HoroscopeAsyncTask)this.getLastCustomNonConfigurationInstance();
if(task != null) {
//pass the new progressbar reference to the asynctask
//implement a method in the asynctask that returns the task result
//e.g. result = task.getResult();
// if the result is not null, it means the task finished its work while orientation
// changed, if the result is null, onPostExecute will take care of that.
//if(result != null) { //set the result in the listview }
} else {
HoroscopeAsyncTask task = new HoroscopeAsyncTask(pb);
task.execute();
}
код пытается получить сохраненные такты, если не один (приложение запущено), выполняет новую асинктическую задачу, если существует одна (изменение ориентации), используйте существующую запущенную асинктическую задачу.
Я полагаю, что частью проблемы может быть то, что изменение ориентации снова вызывает функцию Create.
Посмотрите этот вопрос и проверьте второй ответ.
Простое добавление configChanges в манифест Android не решит проблему, но если вы переопределите onConfigurationChanged, вы можете, например, установить значение SharedPreferences, если вы говорите "AsynTaskStarted=true" или что-то в этом роде, поэтому при изменении ориентации вы можете проверить этот флаг и либо запустите AsyncTask, если его нет, просто пропустите его, если он уже запущен.
Этот другой вопрос, на который ссылается первый ответ на первый связанный вопрос, кажется, имеет больше информации.
Попробуй этот код в манифесте m8 android:configChanges="orientation|keyboardHidden"