应用程序在其主线程上做了太多工作?

时间:2015-06-17 14:24:45

标签: android json multithreading listview memory

我的Android应用程序存在很大问题。在应用程序中,我每隔30秒从JSON流获取数据以更新列表视图 - 如果有新数据,我只更新自定义适配器。如果我一次调用JSONParse / update任务,一切正常,但是当我把这个方法放在一个计时器任务中时,我的应用程序几乎没有运行,最终在10秒后关闭。如果有任何方法可以帮助我,我会非常感激。我很抱歉这里有很多代码。最重要的是,要注意callAsynchonousTask()方法。

这是完成大部分应用程序工作的类:

public class LiveStreamFragment  extends Fragment{

public WXYCMediaPlayer mediaPlayer;

ListView list;
TextView song;
TextView artist;

public ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();

private static String wxycUrl = "http://www.wxyc.info/playlists/recentEntries?v=2";
private static String streamURL = "http://152.2.204.90:8000/wxyc.mp3";

private static final String TAG_PLAYCUTS = "playcuts";
private static final String TAG_SONG = "songTitle";
private static final String TAG_ARTIST = "artistName";
private static final String TAG_ALBUM = "releaseTitle";
private static final String TAG_TALKSETS = "talksets";
private static final String TAG_CHRONID = "chronOrderID";
private static final String TAG_BREAKPOINTS = "breakpoints";
private static final String TAG_HOUR = "hour";
private static final String TAG_LAYOUT = "layoutType";

private SwipeRefreshLayout swipeLayout;
private Button update_button;

private JSONArray playcuts = null;
private JSONArray talksets = null;
private JSONArray breakpoints = null;

private Playcut[] playcutArr;
private Talkset[] talksetArr;
private Breakpoint[] breakpointArr;

public View rootView;

boolean firstCall = true;
boolean buttonActivated;

LiveAdapter adapter;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    rootView = inflater.inflate(R.layout.stream_fragment, container, false);

    list = (ListView) rootView.findViewById(R.id.list);
    adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
    list.setAdapter(adapter);

    buttonActivated = false;

    new JSONParse().execute();
    this.callAsynchronousTask();

    update_button = (Button) rootView.findViewById(R.id.update_button);
    update_button.setText("New Tracks!");
    update_button.setGravity(Gravity.CENTER_HORIZONTAL);
    update_button.setVisibility(View.GONE);
    update_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            adapter.updateDataList(oslist);
            update_button.setVisibility(View.GONE);
            buttonActivated = false;
        }
    });

   list.setOnScrollListener(new AbsListView.OnScrollListener() {
       @Override
       public void onScrollStateChanged(AbsListView view, int scrollState) {
           if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
               if(buttonActivated) {
                   update_button.setVisibility(View.VISIBLE);
               }
           }
       }

       @Override
       public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
               if(buttonActivated) {
                   update_button.setVisibility(View.GONE);
               }
       }
   });

    return rootView;
}

public void addHeartData(HashMap<String, String> heartMap){
    Bus bus = new Bus();
    BusProvider.getInstance().post(heartMap);
}

/******** Calling the JSON Feed to update every 30 seconds ********/
public void callAsynchronousTask() {
    final Handler handler = new Handler();
    Timer timer = new Timer();
    TimerTask doAsynchronousTask = new TimerTask() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    try {
                         new JSONParse().execute();

                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                    }
                }
            });
        }
    };
    timer.schedule(doAsynchronousTask, 0, 30000); //execute in every 50000 ms
}

/******** JSON Parsing and sorting class ********/
public class JSONParse extends AsyncTask<String, String, JSONObject> {
    private ProgressDialog pDialog;

    private String chronIDCheck;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        oslist = new ArrayList<HashMap<String, String>>();

        /*DELAY THIS TASK FOR THE SPLASH SCREEN TIME*/
        //mediaPlayer = new WXYCMediaPlayer(streamURL, this.getActivity());

        //HashMap<String, String> streamMap = new HashMap<String, String>(); //Add this to the media player method.
        //streamMap.put(TAG_LAYOUT, "LiveStream");
        //oslist.add(streamMap);

        /*list = (ListView) rootView.findViewById(R.id.list);
        adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
        list.setAdapter(adapter);*/
    }

    @Override
    protected JSONObject doInBackground(String... args) {
        JSONParser jParser = new JSONParser();
        // Getting JSON from URL
        JSONObject json = jParser.getJSONFromUrl(wxycUrl);

        return json;
    }

    @Override
    protected void onPostExecute(JSONObject json) {
        try {

            playcuts = json.getJSONArray(TAG_PLAYCUTS);
            talksets = json.getJSONArray(TAG_TALKSETS);
            breakpoints = json.getJSONArray(TAG_BREAKPOINTS);

            playcutArr = new Playcut[playcuts.length()];
            talksetArr = new Talkset[talksets.length()];
            breakpointArr = new Breakpoint[breakpoints.length()];

            for(int i = 0; i < playcuts.length(); i++){
                JSONObject playcut = playcuts.getJSONObject(i);

                playcutArr[i] = new Playcut(
                        playcut.getString(TAG_SONG),
                        playcut.getString(TAG_ARTIST),
                        playcut.getString(TAG_ALBUM),
                        playcut.getInt(TAG_CHRONID));
            }

            for(int j = 0; j < talksets.length(); j++){
                JSONObject talkset = talksets.getJSONObject(j);

                talksetArr[j] = new Talkset(
                        talkset.getInt(TAG_CHRONID));

            }

            for(int k = 0; k < breakpoints.length(); k++){
                JSONObject breakpoint = breakpoints.getJSONObject(k);

                breakpointArr[k] = new Breakpoint(
                        breakpoint.getInt(TAG_CHRONID),
                        breakpoint.getLong(TAG_HOUR)
                );
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        int playcutIndex = 0;
        int talksetIndex = 0;
        int breakpointIndex = 0;
        int minID;
        int i = 0;

        /******** Algorithm to consolidate playcuts, breakpoints, and talksets into one arraylist by their chronological ID ********/

        while(i < 30){

            HashMap<String, String> map = new HashMap<String, String>();

            minID = Math.max(
                    playcutArr[playcutIndex].chronID, (int) Math.max(
                            talksetArr[talksetIndex].chronID, breakpointArr[breakpointIndex].chronID
                    )
            );

            if(minID == playcutArr[playcutIndex].chronID) {

                map.put(TAG_SONG, playcutArr[playcutIndex].song);
                map.put(TAG_ARTIST, playcutArr[playcutIndex].artist);
                map.put(TAG_ALBUM, playcutArr[playcutIndex].album);
                map.put(TAG_LAYOUT, "Playcut");
                map.put(TAG_CHRONID,""+playcutArr[playcutIndex].chronID);

                StringBuilder stringBuilder = new StringBuilder("http://ws.audioscrobbler.com/2.0/");
                stringBuilder.append("?method=album.getinfo");
                stringBuilder.append("&api_key=");
                stringBuilder.append("2ead17554acf667f27cf7dfd4c368f15");
                String albumURL = null;

                try {
                    stringBuilder.append("&artist=" + URLEncoder.encode(map.get(TAG_ARTIST), "UTF-8"));
                    stringBuilder.append("&album=" + URLEncoder.encode(map.get(TAG_ALBUM), "UTF-8"));
                    albumURL = new RetrieveAlbumArtUrlTask().execute(stringBuilder.toString()).get();

                } catch (UnsupportedEncodingException e) {
                    albumURL = null;
                } catch (InterruptedException e) {
                    albumURL = null;
                } catch (ExecutionException e) {
                    albumURL = null;
                } catch (IllegalArgumentException e) {
                    albumURL = null;
                }

                map.put("albumArtUrl", albumURL);

                playcutIndex = playcutIndex + 1;
            }

            if(minID == talksetArr[talksetIndex].chronID) {

                map.put(TAG_SONG, "Talkset");
                map.put(TAG_ARTIST, null);
                map.put(TAG_LAYOUT, "Talkset");
                map.put(TAG_CHRONID,""+talksetArr[talksetIndex].chronID);



                talksetIndex = talksetIndex + 1;
            }

            if(minID == breakpointArr[breakpointIndex].chronID) {

                map.put(TAG_SONG, "Breakpoint");
                map.put(TAG_ARTIST, null);
                map.put(TAG_LAYOUT, "Breakpoint");
                map.put(TAG_HOUR, ""+breakpointArr[breakpointIndex].hour);        
                   map.put(TAG_CHRONID,""+breakpointArr[breakpointIndex].chronID);

                breakpointIndex = breakpointIndex + 1;
            }

            map.put("Clicked", "False");



            oslist.add(map);

            chronIDCheck = oslist.get(0).get(TAG_CHRONID);
            i++;

        }

         /* If this is the first JSON Parse, we instantiate the adapter, otherwise we just update */
         if(firstCall) {

             list = (ListView) rootView.findViewById(R.id.list);
             adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
             list.setAdapter(adapter);

             firstCall = false;

         } else {

            if(!adapter.chronIdCheck().equals(oslist.get(0).get(TAG_CHRONID)))    {
                //adapter.updateDataList(oslist);
                update_button.setVisibility(View.VISIBLE);
                buttonActivated = true;

            }

         }
    }

 }

}

这是我的新doInBackground()代码:

@Override
    protected Void doInBackground(String... args) {
        jParser = new JSONParser();
        json = jParser.getJSONFromUrl(wxycUrl);
        Log.v("TEST","BACKGROUND");

        try {

            playcuts = json.getJSONArray(TAG_PLAYCUTS);
            talksets = json.getJSONArray(TAG_TALKSETS);
            breakpoints = json.getJSONArray(TAG_BREAKPOINTS);

            playcutArr = new Playcut[playcuts.length()];
            talksetArr = new Talkset[talksets.length()];
            breakpointArr = new Breakpoint[breakpoints.length()];

            for(int i = 0; i < playcuts.length(); i++){
                JSONObject playcut = playcuts.getJSONObject(i);

                playcutArr[i] = new Playcut(
                        playcut.getString(TAG_SONG),
                        playcut.getString(TAG_ARTIST),
                        playcut.getString(TAG_ALBUM),
                        playcut.getInt(TAG_CHRONID));
            }

            for(int j = 0; j < talksets.length(); j++){
                JSONObject talkset = talksets.getJSONObject(j);

                talksetArr[j] = new Talkset(
                        talkset.getInt(TAG_CHRONID));

            }

            for(int k = 0; k < breakpoints.length(); k++){
                JSONObject breakpoint = breakpoints.getJSONObject(k);

                breakpointArr[k] = new Breakpoint(
                        breakpoint.getInt(TAG_CHRONID),
                        breakpoint.getLong(TAG_HOUR)
                );
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }



        int playcutIndex = 0;
        int talksetIndex = 0;
        int breakpointIndex = 0;
        int minID;
        int i = 0;

        /******** Algorithm to consolidate playcuts, breakpoints, and talksets into one arraylist by their chronological ID ********/

        while(i < 30){

            HashMap<String, String> map = new HashMap<String, String>();

            minID = Math.max(
                    playcutArr[playcutIndex].chronID, (int) Math.max(
                            talksetArr[talksetIndex].chronID, breakpointArr[breakpointIndex].chronID
                    )
            );

            if(minID == playcutArr[playcutIndex].chronID) {

                map.put(TAG_SONG, playcutArr[playcutIndex].song);
                map.put(TAG_ARTIST, playcutArr[playcutIndex].artist);
                map.put(TAG_ALBUM, playcutArr[playcutIndex].album);
                map.put(TAG_LAYOUT, "Playcut");
                map.put(TAG_CHRONID,""+playcutArr[playcutIndex].chronID);

                StringBuilder stringBuilder = new StringBuilder("http://ws.audioscrobbler.com/2.0/");
                stringBuilder.append("?method=album.getinfo");
                stringBuilder.append("&api_key=");
                stringBuilder.append("2ead17554acf667f27cf7dfd4c368f15");
                String albumURL = null;

                try {
                    stringBuilder.append("&artist=" + URLEncoder.encode(map.get(TAG_ARTIST), "UTF-8"));
                    stringBuilder.append("&album=" + URLEncoder.encode(map.get(TAG_ALBUM), "UTF-8"));
                    albumURL = new RetrieveAlbumArtUrlTask().execute(stringBuilder.toString()).get();

                } catch (UnsupportedEncodingException e) {
                    albumURL = null;
                } catch (InterruptedException e) {
                    albumURL = null;
                } catch (ExecutionException e) {
                    albumURL = null;
                } catch (IllegalArgumentException e) {
                    albumURL = null;
                }

                map.put("albumArtUrl", albumURL);

                playcutIndex = playcutIndex + 1;
            }

            if(minID == talksetArr[talksetIndex].chronID) {

                map.put(TAG_SONG, "Talkset");
                map.put(TAG_ARTIST, null);
                map.put(TAG_LAYOUT, "Talkset");
                map.put(TAG_CHRONID,""+talksetArr[talksetIndex].chronID);



                talksetIndex = talksetIndex + 1;
            }

            if(minID == breakpointArr[breakpointIndex].chronID) {

                map.put(TAG_SONG, "Breakpoint");
                map.put(TAG_ARTIST, null);
                map.put(TAG_LAYOUT, "Breakpoint");
                map.put(TAG_HOUR, ""+breakpointArr[breakpointIndex].hour);
                map.put(TAG_CHRONID,""+breakpointArr[breakpointIndex].chronID);

                breakpointIndex = breakpointIndex + 1;
            }

            map.put("Clicked", "False");

            oslist.add(map);

            chronIDCheck = oslist.get(0).get(TAG_CHRONID);
            i++;

        }

        Log.v("Test", "Background 2");

        return null;
    }

    @Override
    protected void onPostExecute(Void args) {
        Log.v("TEST","POST");

     /* If this is the first JSON Parse, we instantiate the adapter, otherwise we just update */
        if(firstCall) {

            list = (ListView) rootView.findViewById(R.id.list);
            adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
            list.setAdapter(adapter);

            firstCall = false;

        } else {

            if(!adapter.chronIdCheck().equals(oslist.get(0).get(TAG_CHRONID)))    {
                //adapter.updateDataList(oslist);
                update_button.setVisibility(View.VISIBLE);
                buttonActivated = true;

            }

        }

    }

}

1 个答案:

答案 0 :(得分:1)

在UI线程上调用方法onPostExecute,你正在做很多事情。尝试将代码保留在if(firstCall)的{​​{1}}中,因为这是您需要访问UI的地方。上面的其余代码可以移动到onPostExecute,这是在后台线程上调用的。

来自文档:

  

doInBackground(Params ...),在后台线程上调用   onPreExecute()完成后立即执行。

     

onPostExecute(Result),在后台后的UI线程上调用   计算完成。