2013-07-09 38 views
3

我为一些网站制作了一些RSS阅读器,所以我想在较低版本的Androd 4.0上实现actionbar和viewpager,所以我使用ActionBarSherlock和ViewPagerIndicator杰克沃顿,所以我正在处理碎片。Android AsyncTask:跳过X帧 - 在主线程内工作太多

我想从URL读取一些RSS提要,并且我为那个名为LoadXMLData的AsyncTask类,这里是该类的代码。

LoadXMLData类:

public class LoadXMLData extends AsyncTask<String, RSSFeed, RSSFeed>{ 


private ProgressDialog mProgressDialog; 


private Context context; 
RSSFeed feed; 
private String RSSFEEDURL = "http://balkanandroid.com/feed/"; 

public LoadXMLData(Context context) { 
    this.context = context; 
    mProgressDialog = new ProgressDialog(context); 
    mProgressDialog.setMessage("Molimo Vas, sačekajte. Podaci se učitavaju."); 
} 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 
    mProgressDialog.show(); 
    Log.d("OVDE SAM:", "onPreExecute()"); 
} 

@Override 
protected RSSFeed doInBackground(String... urls) { 
    // Obtain feed 
    DOMParser myParser = new DOMParser(); 
    feed = myParser.parseXml(urls[0]); 
    Log.d("OVDE SAM:", "PARSIRAM XML"); 
    return feed; 
} 



@Override 
protected void onPostExecute(RSSFeed result) { 
    mProgressDialog.dismiss(); 
    super.onPostExecute(result); 
} 

}

另外我有类MainActivity,其延伸SherlockFragmentActivity。

public class MainActivity extends SherlockFragmentActivity { 
BAFragmentAdapter mAdapter; 
RSSFeed feed; 
Application myApp; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    Log.d("OVDE SAM:", "MAIN ACTIVITY"); 

    myApp = getApplication(); 



    mAdapter = new BAFragmentAdapter(getSupportFragmentManager()); 

    ViewPager pager = (ViewPager) findViewById(R.id.pager); 
    pager.setAdapter(mAdapter); 

    TabPageIndicator indicator = (TabPageIndicator) findViewById(R.id.indicator); 
    indicator.setViewPager(pager); 

} 

public RSSFeed getFeed() { 
    return feed; 
} 

public void setFeed(RSSFeed feed) { 
    this.feed = feed; 
} 

而最imporatnt我有几个片段类(LatestFragments,PhonesFragments,TabletFragments,ApplicationFragments等),并在每个片段我有几乎相同的代码如下所示。

这里是LatestFragment的完整代码:

public class LatestFragment extends Fragment { 

GridView lv; 
RSSFeed feed; 
CustomListAdapter adapter; 
private String RSSFEEDURL = "http://balkanandroid.com/feed/"; 

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.fragment_najnovije, container, 
      false); 


    AsyncTask<String, RSSFeed, RSSFeed> xml = new LoadXMLData(getActivity()) 
      .execute(RSSFEEDURL); 

    // AsyncTask<String, RSSFeed, RSSFeed> load = new 
    // LoadXMLData(getActivity()).execute(RSSFEEDURL); 

    try { 
     feed = xml.get(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    lv = (GridView) view.findViewById(R.id.GridView1); 

    // Set an Adapter to the ListView 
    adapter = new CustomListAdapter(); 
    lv.setAdapter(adapter); 

    // Set on item click listener to the ListView 
    lv.setOnItemClickListener(new OnItemClickListener() { 

     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 
       long arg3) { 
      // actions to be performed when a list item clicked 
      int pos = arg2; 

      Bundle bundle = new Bundle(); 
      bundle.putSerializable("feed", feed); 
      Intent intent = new Intent(getActivity(), DetailsActivity.class); 
      intent.putExtras(bundle); 
      intent.putExtra("pos", pos); 
      startActivity(intent); 

     } 
    }); 

    return view; 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    adapter.imageLoader.clearCache(); 
    adapter.notifyDataSetChanged(); 
} 

class CustomListAdapter extends BaseAdapter { 

    private LayoutInflater layoutInflater; 
    public ImageLoader imageLoader; 

    public CustomListAdapter() { 

     layoutInflater = (LayoutInflater) getActivity().getSystemService(
       Context.LAYOUT_INFLATER_SERVICE); 
     imageLoader = new ImageLoader(getActivity().getApplicationContext()); 
    } 

    public int getCount() { 
     // TODO Auto-generated method stub 
     // Set the total list item count 
     return feed.getItemCount(); 
    } 

    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; 
     if (listItem == null) { 
      listItem = layoutInflater.inflate(R.layout.list_item, null); 
     } 

     // Initialize the views in the layout 
     ImageView iv = (ImageView) listItem.findViewById(R.id.thumb); 
     TextView tvTitle = (TextView) listItem.findViewById(R.id.title); 
     TextView tvDate = (TextView) listItem.findViewById(R.id.tvDate); 

     // Set the views in the layout 
     imageLoader.DisplayImage(feed.getItem(pos).getImage(), iv); 
     tvTitle.setText(feed.getItem(pos).getTitle()); 
     tvDate.setText(feed.getItem(pos).getDate()); 

     return listItem; 
    } 

} 

}

正如你可以看到我用的AsyncTask类LoadXMLData读取数据doInBackground()方法,然后我使用此代码在所有片段类下调用AsyncTask类,因为我需要RSSFeed的结果,因为我需要该数据将其显示给用户。

AsyncTask<String, RSSFeed, RSSFeed> xml = new LoadXMLData(getActivity()) 
      .execute(RSSFEEDURL); 

    try { 
     feed = xml.get(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

和它的作品,但是当我点击从视图寻呼机打开其他视图的缓慢,几乎冻结我的应用程序,和我得到的logcat此消息。

07-10 00:22:40.598:I/Choreographer(623):跳过了316帧!应用程序可能在其主线程上做了太多工作。

回答

3

这是因为您在AsyncTask上拨打get(),哪个阻止。不要这样做。

请改为使用AsyncTask的中的Feed。

+0

我认为这是因为这一点。无论如何,我可以从我的片段类中的onPostExecute获取该提要吗? – Zookey

+0

@Zookey:一种方法是让'AsyncTask'成为正在讨论的片段的内部类,并将片段标记为'setRetainInstance(true)'。然后,您可以根据需要使用'onPostExecute()'中的片段调用方法,同时使用'setRetainInstance(true)'确保片段在配置更改期间保持不变。或者,开始使用某种消息总线('LocalBroadcastManager',Square的Otto,greenrobot的EventBus等),并从'onPostExecute()'发送一条消息以供片段拾取(如果它仍然在)。 – CommonsWare

+0

听起来很复杂! :)有什么好的例子与异步任务和片段的工作? – Zookey

相关问题