Listfragmentでは、 JSONの結果をオンライン サーバー(1,2,3,4) から読み込むことができますが、ホーム ボタンを押してアプリに戻ると、Listview に重複したリスト (1,2,3, 4,1,2,3,4)、画面を回転させると時々発生します。
私はたくさん読んでいます...そしてたくさんの投稿がありますが、さまざまなケースがあるので、ここに私のケースがあります...
私のUI ... ViewPager > ListFragment
ListFragment : ローダー、AsyncTaskLoader、BaseAdapter、JSON、HashMap
使用しない/私の場合ではない: Cursors、SQLite、ContentProvider、Activity、ListActivity、String[]
はい... httpclient を httpurlconnection に変更します:)
さらに良くなった...別のアクティビティから ListFragment に戻り、アイテムを選択すると... アプリがクラッシュします!!!、LogCat は次のように述べています:「アダプターのコンテンツが変更されましたが、ListView は通知を受け取りませんでした」アダプターのコンテンツがバックグラウンド スレッドからではなく、UI スレッドからのみ変更されていることを確認してください。
runOnUiThread()を試してみたかったのですが、明らかに ListFragment では機能しませんが、ListActivity では機能しません...私の場合はそうではありません。
履歴書:この 2 つの問題は、onLoadingBackground() のプロセスと onLoadingFinish() のプロセスがうまく解決できないためだと思います。:S
そして... 私は使っています... 私はandroid:configChanges="orientation|screenSize"
気分が悪い、それは不正行為です!!! xD
念のため... 私は Volley を使用していません。なぜなら、JAVA/Android のロジックについてもっと学びたいからです。また、Volley で問題が発生した場合に...質問に答える人が少ないからです :S
私はこれを求めたくありませんでしたが... 数時間前に投稿を読みました.
なに???そして、私はこれで 3 週間以上立ち往生しています。:S (下手な英語でごめんなさい... がんばっています、スペイン語を話します)
public class miNewFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<Model>> {
static ParseadorJSON_func ParseadorJSON_objeto = new ParseadorJSON_func();
static ArrayList<HashMap<String, String>> arrayListaCompleta;
private static String urlPagina2 = "http://www.domain.com/json/mi_json.php";
private static final String TAG_SUCCESS = "success";
private static final String TAG_CATEGORIAS = "categorias";
private static final String TAG_PID = "idItem";
private static final String TAG_NAME = "name";
static JSONArray jsonCategorias = null;
private ListView miListView;
myBaseAdapter miAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.categorias, container, false);
miListView = (ListView)rootView.findViewById(android.R.id.list);
arrayListaCompleta = new ArrayList<HashMap<String, String>>();
Log.e("onCreateView = ", "miListView > arrayListacompleta > return rootView");
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
myBaseAdapter miAdapter = new myBaseAdapter(getActivity());
miListView.setAdapter(miAdapter);
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
Log.e("onActivityCreated = ", "myBaseAdapter > setAdapter > getLoaderManager");
}
@Override
public Loader<List<Model>> onCreateLoader(int arg0, Bundle arg1) {
Log.e("Loader/onCreateLoader = ", "myAsyncTaskLoader");
return new myAsyncTaskLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<List<Model>> arg0, List<Model> data) {
miAdapter = new myBaseAdapter(getActivity());
miListView.setAdapter(miAdapter);
miAdapter.notifyDataSetChanged();
Log.e("Loader/onLoadFinished = ", "myBaseAdapter > setAdapter > notifyDataSetChanged");
}
@Override
public void onLoaderReset(Loader<List<Model>> arg0) {
Log.e("Loader/onLoaderReset = ", "Nothing");
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Log.e("onListItemClick = ", "Nothing");
}
public class myBaseAdapter extends BaseAdapter {
private Context mContext;
public myBaseAdapter(Context c) {
mContext = c;
}
public int getCount() {
return arrayListaCompleta.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder = null;
if (convertView == null) {
holder = new Holder();
LayoutInflater ltInflate = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
convertView = ltInflate.inflate(R.layout.categorias_list_item, null);
holder.h_categTag = (TextView) convertView.findViewById(R.id.categTag);
holder.h_categIdItem = (TextView) convertView.findViewById(R.id.categIdItem);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.h_categTag.setText( arrayListaCompleta.get(position).get("name").toString() );
holder.h_categIdItem.setText( arrayListaCompleta.get(position).get("idItem").toString() );
return convertView;
}
class Holder {
TextView h_categTag;
TextView h_categIdItem;
}
}
public static class myAsyncTaskLoader extends AsyncTaskLoader<List<Model>> {
List<Model> mModels;
public myAsyncTaskLoader(Context context) {
super(context);
}
@Override
public List<Model> loadInBackground() {
Log.e("Async/loadInBackground = ", "Creating Array from JSON");
List<NameValuePair> arrayDelServidor = new ArrayList<NameValuePair>();
JSONObject jsonCompleto = ParseadorJSON_objeto.makeHttpRequest(urlPagina2, "GET", arrayDelServidor);
try {
int success = jsonCompleto.getInt(TAG_SUCCESS);
if (success == 1) {
jsonCategorias = jsonCompleto.getJSONArray(TAG_CATEGORIAS);
for (int i = 0; i < jsonCategorias.length(); i++) {
JSONObject jsonFila = jsonCategorias.getJSONObject(i);
String id = jsonFila.getString(TAG_PID);
String name = jsonFila.getString(TAG_NAME);
HashMap<String, String> mapaDatos = new HashMap<String, String>();
mapaDatos.put(TAG_PID, id);
mapaDatos.put(TAG_NAME, name);
arrayListaCompleta.add(mapaDatos);
}
} else {
//nada
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
public void deliverResult(List<Model> listOfData) {
if (isReset()) {
Log.e("Async/deliverResult = ", "isReset()");
if (listOfData != null) {
onReleaseResources(listOfData);
}
}
List<Model> oldApps = listOfData;
mModels = listOfData;
if (isStarted()) {
Log.e("Async/deliverResult = ", "isStarted()");
super.deliverResult(listOfData);
}
if (oldApps != null) {
Log.e("Async/deliverResult = ", "oldApps");
onReleaseResources(oldApps);
}
}
@Override
protected void onStartLoading() {
if (mModels != null) {
deliverResult(mModels);
Log.e("Async/onStartLoading = ", "mModels != null");
}
if (takeContentChanged()) {
forceLoad();
Log.e("Async/onStartLoading = ", "takeContentChanged()");
}
if (mModels == null) {
forceLoad();
Log.e("Async/onStartLoading = ", "mModels == null");
}
}
@Override
protected void onStopLoading() {
cancelLoad();
Log.e("Async/onStopLoading = ", "cancelLoad()");
}
@Override
public void onCanceled(List<Model> apps) {
super.onCanceled(apps);
onReleaseResources(apps);
Log.e("Async/onCanceled = ", "onReleaseResources(apps)");
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
if (mModels != null) {
onReleaseResources(mModels);
mModels = null;
Log.e("Async/onReset = ", "onReleaseResources(mModels)");
}
}
protected void onReleaseResources(List<Model> apps) {
Log.e("Async/onReleaseResources = ", "Entró pero no hizo nada");
}
}
}
そして、誰かがこれらのコードを必要とする場合...
final class Model {
private String name;
private String id;
public Model(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
public static class ParseadorJSON_func {
InputStream is = null;
JSONObject jObj = null;
String json = "";
public ParseadorJSON_func() {
}
public JSONObject makeHttpRequest(String url, String method, List<NameValuePair> arrayDesdeServidor) {
try {
if(method == "POST"){
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(arrayDesdeServidor));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}else if(method == "GET"){
DefaultHttpClient httpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(arrayDesdeServidor, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
}
.
編集: loadInBackground()
アクティビティからこの Listfragment に戻り、アイテムを選択すると、loadInBackground がアダプターのコンテンツを変更し、コンテンツを更新しないため、アプリがクラッシュしました。さて、これでif else ...アダプターがnullかどうかをチェックし、loadInBackgroundを実行するかどうかを確認するため、アプリはクラッシュしませんが...
私がやった方法は...おそらく最も適切な方法ではないと思います.私はそこに到達していませんが、結果を更新または追加したいときは...この方法はうまくいかないかもしれません. ヘルプ/例はありますか?
@Override
public List<Model> loadInBackground() {
Log.e("Async/loadInBackground = ", "Creating Array from JSON");
//NEW if else...
if( miAdapter != null ){
adaptadorEstado = "No es Null";
}else{
adaptadorEstado = "Si es Null";
List<NameValuePair> arrayDelServidor = new ArrayList<NameValuePair>();
JSONObject jsonCompleto = ParseadorJSON_objeto.makeHttpRequest(urlPagina2, "GET", arrayDelServidor);
try {
int success = jsonCompleto.getInt(TAG_SUCCESS);
if (success == 1) {
jsonCategorias = jsonCompleto.getJSONArray(TAG_CATEGORIAS);
for (int i = 0; i < jsonCategorias.length(); i++) {
JSONObject jsonFila = jsonCategorias.getJSONObject(i);
String id = jsonFila.getString(TAG_PID);
String name = jsonFila.getString(TAG_NAME);
HashMap<String, String> mapaDatos = new HashMap<String, String>();
mapaDatos.put(TAG_PID, id);
mapaDatos.put(TAG_NAME, name);
arrayListaCompleta.add(mapaDatos);
}
} else {
//nada
}
} catch (JSONException e) {
e.printStackTrace();
}
}//end new if else
Log.e("Async/loadInBackground = ", "Adaptador > "+adaptadorEstado);
return null;
}
.
新規: onConfigurationChanged()
私は不正行為をしていたので、android:configChanges="orientation|screenSize"
試してみましたが、これがマニフェストに残っているonConfigurationChanged()
場合にのみ機能/応答します。configChanges
したがって、この問題は、loadInBackground() を解決しようとする方法に関係していると思いますが、よくわかりません。
一方...私onCreate
はMainActivityの作成について多くのことを読んで、 savedInstanceState
nullかどうかを確認してから、「getSupportFragmentManager()。beginTransaction()。findFragmentByTag()」のようなものを使用し、試してみると...私の MainActivity ではmiPagerAdapter = new funcionPagerAdapter(getSupportFragmentManager());
、おそらく私の場合は...別の方法で解決すると思うので、このことは機能しないことがわかりました...しかし、方法がわかりません! :S
//In my ListFragment...
@Override
public void onConfigurationChanged(Configuration congfValues) {
super.onConfigurationChanged(congfValues);
Log.e("onConfigurationChanged = ", "Si entró");
if( miAdapter != null ){
Log.e("onConfigurationChanged = ", "Adaptador Lleno");
}else{
miAdapter = new myBaseAdapter(getActivity());
miListView.setAdapter(miAdapter);
Log.e("onConfigurationChanged = ", "Adaptador estaba Vacío (ya no)");
}
}
//In my MainActivity (onCreate)
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.home_viewpager);
Fragment_categorias miFragCategoria;
if (savedInstanceState!= null) {
miFragCategoria = (Fragment_categorias) getSupportFragmentManager().findFragmentByTag("tagCategoria");
} else {
miFragCategoria = new Fragment_categorias();
getSupportFragmentManager().beginTransaction().add(R.id.(i dont know), miFragCategoria, "tagCategoria").commit();
}
//viewpager
miPagerAdapter = new funcionPagerAdapter(getSupportFragmentManager());
miViewPager = (ViewPager) findViewById(R.id.vpContenedor);
miViewPager.setOffscreenPageLimit(5);
miViewPager.setAdapter(miPagerAdapter);
}