如何在查询远程服务器并更新屏幕后调试缓慢的Android异步响应



我有一个Android应用程序,它使用相同的服务器PHP脚本在数据库中做一些事情并做出响应,然后相应地更新你的屏幕。

大约 60% 的时间它很快。但有时手机的UI长时间挂起,这确实让用户感到困惑,因为他们认为出了问题。

此外,如果应用程序屏幕长时间挂起,我只是引用它,我看到数据都在那里,所以问题出在数据插入数据库之后。

这是我的安卓代码:

我有一个扩展 BaseListActivity 的 TopicActivity 扩展了 ListActivity

在主题活动中,我首先设置了如下列表:

DiscussionMessage d = new DiscussionMessage ();
d.setMessage( "Please wait while the discussion load..." );
discussion.add(d);
adapter = new ArrayAdapter<DiscussionMessage>( 
        this,R.layout.discussion_comments, 
        discussion);
setListAdapter(adapter);

然后当发生某些事情时,我调用 sendFeedback 方法,如下所示:

public void sendFeedback( String c , String user_id , String problem_id , 
        String recent_topic_id )
{  
    String[] params = new String[] 
            { "the_remote_url", 
             c , user_id, problem_id , recent_topic_id };
    AddComment task = new AddComment();
    task.execute(params);        
}

然后是AddComment类的外观。 它位于 TopicActivity 类中:

public class AddComment extends AsyncTask<String, Void, String> 
{
    @Override
    protected String doInBackground(String... theParams) 
    {
        String myUrl = theParams[0];
        final String comment = theParams[1];
        final String user_id = theParams[2];
        final String problem_id = theParams[3];
        final String recent_topic_id = theParams[4];
        String charset = "UTF-8";           
        String response = null;
        try 
        {                           
            String query = String.format("comment=%s&user_id=%s&problem_id=%s&recent_topic_id=%s", 
                     URLEncoder.encode( comment, charset), 
                     URLEncoder.encode( user_id, charset), 
                     URLEncoder.encode( problem_id, charset), 
                     URLEncoder.encode( recent_topic_id, charset)
                     );             
            final URL url = new URL( myUrl + "?" + query );
            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true); 
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.connect();
            InputStream stream = conn.getInputStream();
            byte[] stream_buffer = new byte[8196];
            int readCount;
            StringBuilder stream_builder = new StringBuilder();
            while ((readCount = stream.read(stream_buffer)) > -1) 
            {
                stream_builder.append(new String(stream_buffer, 0, readCount));
            }
        } 
        catch (Exception e) 
        {
                e.printStackTrace();
        }
        return response;
    }
    @Override
    protected void onPostExecute(String result) 
    {
        if ( result != null )
        {
         Toast.makeText(getApplicationContext(), "Could not get the current discussion.", Toast.LENGTH_LONG).show();                                
        }
        else
        {               
            try
            {
                JSONArray obj = new JSONArray(result);
                if ( obj != null )
                {
                    discussion.clear();
                    if ( obj.length() == 0 )
                    {
                        DiscussionMessage message = new DiscussionMessage ( );
                        message.setMessage("No messages in this discussion.");
                        discussion.add( message );
                    }
                    else
                    {
                        for ( int i = 0; i < obj.length(); i++ )
                        {
                            JSONObject o = obj.getJSONObject(i);
                            String comment = o.getString("comment");
                            String commenter_id = o.getString("commenter_id");
                            String comment_id = o.getString("comment_id");
                            String first_name = o.getString("first_name");
                            String last_name = o.getString("last_name");
                            String is_private = o.getString("is_private");
                            DiscussionMessage d = new DiscussionMessage ( );
                            d.setMessage(comment);
                            d.setAuthorId(commenter_id);
                            d.setMessageId(comment_id); 
                            d.setAuthorName(first_name);                                
                            discussion.add( d );
                        }
                    }
                    adapter.notifyDataSetChanged(); 
                    // Now clear the text area of text.
                    EditText comment = (EditText) findViewById(R.id.discussion_comment);  
                    comment.setText( "" );  
                }                   
            }
            catch ( Exception e )
            {
                   // Do something.
            }
        }
    }        
}        

从中可以判断出我可能做错了什么吗?我如何使用异步或列表适配器可能有问题吗?

非常感谢修复

和/或调试此问题的想法!

将 JSON 解析和创建 DiscussionMessage 对象移动到 doInBackground() ,因为它们需要时间并且应该在后台线程上运行。将DiscussionMessage物体倒入Adapter中,并在onPostExecute()中调用notifyDataSetChanged()

除此之外,正如Fuzzical Logic指出的那样,你需要精确地确定你的困难在哪里,无论是使用Log调用还是Traceview或其他什么。例如,您的 Web 服务有时响应速度很慢吗?

最新更新