【问题标题】:Avoid Fetching Data from JSON again and again避免一次又一次地从 JSON 中获取数据
【发布时间】:2016-04-07 05:06:45
【问题描述】:

我在 MainActivity 中解析来自服务器的 JSON 数据,但是每当我切换到另一个 Activity 然后再次调用 MainActivity... 问题就来了,它再次访问 JSON url,再次从 JSON 中获取数据。

为什么?而我已经从 JSON 下载了数据

public class MainActivity extends Activity {

    ArrayList<Actors> actorsList;

    ActorAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        actorsList = new ArrayList<Actors>();
        new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");

        ListView listview = (ListView)findViewById(R.id.list);
        adapter = new ActorAdapter(getApplicationContext(), R.layout.row, actorsList);

        listview.setAdapter(adapter);

        listview.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                    long id) {
                // TODO Auto-generated method stub
                Toast.makeText(getApplicationContext(), actorsList.get(position).getName(), Toast.LENGTH_LONG).show();              
            }
        });
    }


    class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {

        ProgressDialog dialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = new ProgressDialog(MainActivity.this);
            dialog.setMessage("Loading, please wait");
            dialog.setTitle("Connecting server");
            dialog.show();
            dialog.setCancelable(false);
        }

        @Override
        protected Boolean doInBackground(String... urls) {
            try {

                //------------------>>
                HttpGet httppost = new HttpGet(urls[0]);
                HttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = httpclient.execute(httppost);

                // StatusLine stat = response.getStatusLine();
                int status = response.getStatusLine().getStatusCode();

                if (status == 200) {
                    HttpEntity entity = response.getEntity();
                    String data = EntityUtils.toString(entity);


                    JSONObject jsono = new JSONObject(data);
                    JSONArray jarray = jsono.getJSONArray("actors");

                    for (int i = 0; i < jarray.length(); i++) {
                        JSONObject object = jarray.getJSONObject(i);

                        Actors actor = new Actors();

                        actor.setName(object.getString("name"));
                        actor.setDescription(object.getString("description"));
                        actor.setDob(object.getString("dob"));
                        actor.setCountry(object.getString("country"));
                        actor.setHeight(object.getString("height"));
                        actor.setSpouse(object.getString("spouse"));
                        actor.setChildren(object.getString("children"));
                        actor.setImage(object.getString("image"));

                        actorsList.add(actor);
                    }
                    return true;
                }

                //------------------>>

            } catch (ParseException e1) {
                e1.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return false;
        }

        protected void onPostExecute(Boolean result) {
            dialog.cancel();
            adapter.notifyDataSetChanged();
            if(result == false)
                Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();

        }
    }   
}

【问题讨论】:

  • 你可以放flag来解决这个问题
  • 当您为其他活动触发意图时,您是否正在完成 MainActivity
  • 您可以为此在 SharedPreference 中放置一个标志并检查该标志。
  • 两种方式 - 我使用 onBackPressed() 从 SecondActivity 调用 MainActivity 并使用 Intent 从 ThirdActivity 调用 MainActivity ... 那么最好的方法是什么?
  • 使用共享首选项或制作标志

标签: java android json android-activity lifecycle


【解决方案1】:

尝试使用静态变量

 static boolean flag=false;
 static ArrayList<Actors> actorsList;

然后在调用 AsyncTask 之前检查标志是真还是假

if(!flag){
 actorsList = new ArrayList<Actors>(); //use this inside if statement
 new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");
flag=true;
}

所以只有当标志为假时才会执行异步任务... 希望这会有所帮助。

【讨论】:

  • 是的,现在它不再访问 JSON api,但甚至没有将现有数据显示到 ListView 中......可能是什么原因?
  • @Oreo 它没有点击 api 那么您如何在列表视图中获取数据,因为您的数组列表正在填充您的异步任务。您应该使用单例方法通过调用您的方法来保存您获得的数据api 第一次。
  • 是否有异常被调用?
  • @Ben 没有,但没有将现有数据放入 ListView(我第一次点击 json 时得到的数据)
  • 尝试将actorList设为静态
【解决方案2】:

根据您的评论“I am calling MainActivity from SecondActivity using onBackPressed() and also calling MainActivity from ThirdActivity using Intent.

在 SecondActivity onBackPressed() :简单地调用 finish() 不会重新加载 MainActivity,因此它不会重新加载并再次调用 web 服务。

另一种选择是有一个标志,保存在shared preferences

步骤:

  1. 第一次调用服务时,将标志 didCallService = true 保存到共享首选项。将 json 响应也保存在 shared preference 中作为字符串。

  2. 当您从其他 2 个活动到达 MainActivity 上的 onCreate() 时,请检查用户默认值中的 didCallService 是否为真。如果是这样,请不要再次调用该服务。

【讨论】:

    【解决方案3】:

    取一个boolean 变量并将其初始化为true,并将其状态保存到sharedpreference。现在当MainActivity 启动时,使用sharedpreference 检查这个boolean 是否为真。如果为真,则获取JSON 并将boolean 设置为假,并将boolean 的状态保存为sharedpreference。现在,每当调用 MainActivity 之后,因为 boolean 为 false,JSON 将不会被获取。

    【讨论】:

      【解决方案4】:

      您可以为此使用“savedInstanceState”变量,请查看以下代码

      if(savedInstanceState==null)
      {
           new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");
      }
      

      当你第一次开始活动时,它的 savedInstanceState 下次 t 有值时为空,所以在你的代码中添加上述条件。

      【讨论】:

      • 回复评论对你有帮助吗?
      • 试过这个:pastebin.com/fCLZDXK4 请让我知道我错过了什么?
      • YES 获取 NPE - listview.setAdapter(adapter);从 SecondActivity 到 MainActivity 时,我得到了 NPE
      • 请调试它我认为空指针的json调用问题已经解决了很多次我认为apater对象有空值调试和适配器的检查值,并且还检查了很多时间json调用问题是否解决
      【解决方案5】:

      使用singleTask

      在您的AndroidManifest.xml 文件中将此属性添加到MainActivity

      <activity ..
            android:launchMode= "singleTask" />
      

      这将重新加载 MainActivity 的实例,并且不会调用 onCreate(),而是可以在 onNewIntent() 方法中使用新的 Intent。

      【讨论】:

      • 当我从 SecondActivity 到 MainActivity 时,尝试仍然访问 JSON api
      • 我不相信这一点,你有代码只能在 onCreate() 中获取并且仍然使用 singleTask 进行获取,神奇。!
      • 实际上发生了什么,对于第一个显示进度对话框 > 获取数据 > 填充列表视图然后我移动到第二个活动,现在我再次点击返回(我看到的)显示进度对话框 > 获取数据 > 填充列表视图
      • 我没有在 MainActivity 的任何地方使用完成,像这样调用 SecondActivity:listview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView> arg0, View arg1, int position, long id) { // TODO 自动生成的方法存根 Toast.makeText(getApplicationContext(),actorsList.get(position).getName(), Toast.LENGTH_LONG).show(); Intent intent = new Intent(MainActivity.this, SecondActivity .class); startActivity(intent); } });
      • 使用this answer,把你的代码在null条件下执行任务。
      猜你喜欢
      • 2015-04-15
      • 2013-05-06
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-01
      • 1970-01-01
      相关资源
      最近更新 更多