楼主: 熊猫儿

[转载] 【Android的一些重要知识7。。。。】

[复制链接]
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
81#
 楼主| 发表于 2018-3-7 11:11 | 只看该作者
都没撒好说的,很简单~


5、主Activity
[java] view plain copy


  • package com.example.android_robot_01;  
  •   
  • import java.util.ArrayList;  
  • import java.util.Date;  
  • import java.util.List;  
  •   
  • import android.app.Activity;  
  • import android.content.Context;  
  • import android.os.Bundle;  
  • import android.os.Handler;  
  • import android.os.Message;  
  • import android.text.TextUtils;  
  • import android.view.View;  
  • import android.view.Window;  
  • import android.view.inputmethod.InputMethodManager;  
  • import android.widget.EditText;  
  • import android.widget.ListView;  
  • import android.widget.Toast;  
  •   
  • import com.example.android_robot_01.bean.ChatMessage;  
  • import com.example.android_robot_01.bean.ChatMessage.Type;  
  • import com.zhy.utils.HttpUtils;  
  •   
  • public class MainActivity extends Activity  
  • {  
  •     /**
  •      * 展示消息的listview
  •      */  
  •     private ListView mChatView;  
  •     /**
  •      * 文本域
  •      */  
  •     private EditText mMsg;  
  •     /**
  •      * 存储聊天消息
  •      */  
  •     private List<ChatMessage> mDatas = new ArrayList<ChatMessage>();  
  •     /**
  •      * 适配器
  •      */  
  •     private ChatMessageAdapter mAdapter;  
  •   
  •     private Handler mHandler = new Handler()  
  •     {  
  •         public void handleMessage(android.os.Message msg)  
  •         {  
  •             ChatMessage from = (ChatMessage) msg.obj;  
  •             mDatas.add(from);  
  •             mAdapter.notifyDataSetChanged();  
  •             mChatView.setSelection(mDatas.size() - 1);  
  •         };  
  •     };  


使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
82#
 楼主| 发表于 2018-3-7 11:14 | 只看该作者
  • @Override  
  •     protected void onCreate(Bundle savedInstanceState)  
  •     {  
  •         super.onCreate(savedInstanceState);  
  •         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  •         setContentView(R.layout.main_chatting);  
  •          
  •         initView();  
  •          
  •         mAdapter = new ChatMessageAdapter(this, mDatas);  
  •         mChatView.setAdapter(mAdapter);  
  •   
  •     }  
  •   
  •     private void initView()  
  •     {  
  •         mChatView = (ListView) findViewById(R.id.id_chat_listView);  
  •         mMsg = (EditText) findViewById(R.id.id_chat_msg);  
  •         mDatas.add(new ChatMessage(Type.INPUT, "我是小貅貅,很高兴为您服务"));  
  •     }  
  •   
  •     public void sendMessage(View view)  
  •     {  
  •         final String msg = mMsg.getText().toString();  
  •         if (TextUtils.isEmpty(msg))  
  •         {  
  •             Toast.makeText(this, "您还没有填写信息呢...", Toast.LENGTH_SHORT).show();  
  •             return;  
  •         }  
  •   
  •         ChatMessage to = new ChatMessage(Type.OUTPUT, msg);  
  •         to.setDate(new Date());  
  •         mDatas.add(to);  
  •   
  •         mAdapter.notifyDataSetChanged();  
  •         mChatView.setSelection(mDatas.size() - 1);  
  •   
  •         mMsg.setText("");  
  •   
  •         // 关闭软键盘  
  •         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);  
  •         // 得到InputMethodManager的实例  
  •         if (imm.isActive())  
  •         {  
  •             // 如果开启  
  •             imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT,  
  •                     InputMethodManager.HIDE_NOT_ALWAYS);  
  •             // 关闭软键盘,开启方法相同,这个方法是切换开启与关闭状态的  
  •         }  
  •   
  •         new Thread()  
  •         {  
  •             public void run()  
  •             {  
  •                 ChatMessage from = null;  
  •                 try  
  •                 {  
  •                     from = HttpUtils.sendMsg(msg);  
  •                 } catch (Exception e)  
  •                 {  
  •                     from = new ChatMessage(Type.INPUT, "服务器挂了呢...");  
  •                 }  
  •                 Message message = Message.obtain();  
  •                 message.obj = from;  
  •                 mHandler.sendMessage(message);  
  •             };  
  •         }.start();  
  •   
  •     }  
  •   
  • }  

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
83#
 楼主| 发表于 2018-3-7 11:14 | 只看该作者
为ListView设置数据,一开始就设置了第一句话“我是小貅貅,很高兴为您服务”;还有就是sendButton的事件处理。
6、适配器
[java] view plain copy


  • package com.example.android_robot_01;  
  •   
  • import java.util.List;  
  •   
  • import android.content.Context;  
  • import android.view.LayoutInflater;  
  • import android.view.View;  
  • import android.view.ViewGroup;  
  • import android.widget.BaseAdapter;  
  • import android.widget.TextView;  
  •   
  • import com.example.android_robot_01.bean.ChatMessage;  
  • import com.example.android_robot_01.bean.ChatMessage.Type;  
  •   
  • public class ChatMessageAdapter extends BaseAdapter  
  • {  
  •     private LayoutInflater mInflater;  
  •     private List<ChatMessage> mDatas;  
  •   
  •     public ChatMessageAdapter(Context context, List<ChatMessage> datas)  
  •     {  
  •         mInflater = LayoutInflater.from(context);  
  •         mDatas = datas;  
  •     }  
  •   
  •     @Override  
  •     public int getCount()  
  •     {  
  •         return mDatas.size();  
  •     }  
  •   
  •     @Override  
  •     public Object getItem(int position)  
  •     {  
  •         return mDatas.get(position);  
  •     }  
  •   
  •     @Override  
  •     public long getItemId(int position)  
  •     {  
  •         return position;  
  •     }  
  •   
  •     /**
  •      * 接受到消息为1,发送消息为0
  •      */  http://blog.csdn.net/lmj623565791/article/details/38498353


使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
84#
 楼主| 发表于 2018-3-8 08:57 | 只看该作者
  •   @Override  
  •     public int getItemViewType(int position)  
  •     {  
  •         ChatMessage msg = mDatas.get(position);  
  •         return msg.getType() == Type.INPUT ? 1 : 0;  
  •     }  
  •   
  •     @Override  
  •     public int getViewTypeCount()  
  •     {  
  •         return 2;  
  •     }  
  •   
  •     @Override  
  •     public View getView(int position, View convertView, ViewGroup parent)  
  •     {  
  •         ChatMessage chatMessage = mDatas.get(position);  
  •   
  •         ViewHolder viewHolder = null;  
  •   
  •         if (convertView == null)  
  •         {  
  •             viewHolder = new ViewHolder();  
  •             if (chatMessage.getType() == Type.INPUT)  
  •             {  
  •                 convertView = mInflater.inflate(R.layout.main_chat_from_msg,  
  •                         parent, false);  
  •                 viewHolder.createDate = (TextView) convertView  
  •                         .findViewById(R.id.chat_from_createDate);  
  •                 viewHolder.content = (TextView) convertView  
  •                         .findViewById(R.id.chat_from_content);  
  •                 convertView.setTag(viewHolder);  
  •             } else  
  •             {  
  •                 convertView = mInflater.inflate(R.layout.main_chat_send_msg,  
  •                         null);  
  •   
  •                 viewHolder.createDate = (TextView) convertView  
  •                         .findViewById(R.id.chat_send_createDate);  
  •                 viewHolder.content = (TextView) convertView  
  •                         .findViewById(R.id.chat_send_content);  
  •                 convertView.setTag(viewHolder);  
  •             }  
  •   
  •         } else  
  •         {  
  •             viewHolder = (ViewHolder) convertView.getTag();  
  •         }  
  •   
  •         viewHolder.content.setText(chatMessage.getMsg());  
  •         viewHolder.createDate.setText(chatMessage.getDateStr());  
  •   
  •         return convertView;  
  •     }  
  •   
  •     private class ViewHolder  
  •     {  
  •         public TextView createDate;  
  •         public TextView name;  
  •         public TextView content;  
  •     }  
  •   
  • }  

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
85#
 楼主| 发表于 2018-3-8 08:57 | 只看该作者
唯一需要注意的是,因为我们的ListView的Item有两种显示风格,所以比平时我们需要多重写两个方法:

[java] view plain copy


  • /**
  •      * 接受到消息为1,发送消息为0
  •      */  
  •     @Override  
  •     public int getItemViewType(int position)  
  •     {  
  •         ChatMessage msg = mDatas.get(position);  
  •         return msg.getType() == Type.INPUT ? 1 : 0;  
  •     }  
  •   
  •     @Override  
  •     public int getViewTypeCount()  
  •     {  
  •         return 2;  
  •     }  


getViewTypeCount返回的就是种类数目了;getItemViewType根据当然Item的position决定返回不同的整型变量。然后在getView中,根据消息的类型去加载不同的Item布局即可。


使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
86#
 楼主| 发表于 2018-3-8 08:58 | 只看该作者
Android AsyncTask 源码解析


1、概述

相信大家对AsyncTask都不陌生,对于执行耗时任务,然后更新UI是一把利器,当然也是替代Thread + Handler 的一种方式。如果你对Handler机制还不了解,请看:Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系

2、简单的例子

相信大家都写过这样的代码:


[java] view plain copy


  • package com.example.zhy_asynctask_demo01;  
  •   
  • import android.app.Activity;  
  • import android.app.ProgressDialog;  
  • import android.os.AsyncTask;  
  • import android.os.Bundle;  
  • import android.util.Log;  
  • import android.widget.TextView;  
  •   
  • public class MainActivity extends Activity  
  • {  
  •   
  •     private static final String TAG = "MainActivity";  
  •     private ProgressDialog mDialog;  
  •     private TextView mTextView;  
  •   
  •     @Override  
  •     protected void onCreate(Bundle savedInstanceState)  
  •     {  
  •         super.onCreate(savedInstanceState);  
  •         setContentView(R.layout.activity_main);  
  •   
  •         mTextView = (TextView) findViewById(R.id.id_tv);  
  •   
  •         mDialog = new ProgressDialog(this);  
  •         mDialog.setMax(100);  
  •         mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
  •         mDialog.setCancelable(false);  
  •   
  •         new MyAsyncTask().execute();  
  •   
  •     }  
  •   
  •     private class MyAsyncTask extends AsyncTask<Void, Integer, Void>  
  •     {  
  •   




使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
87#
 楼主| 发表于 2018-3-8 09:03 | 只看该作者
  •   @Override  
  •         protected void onPreExecute()  
  •         {  
  •             mDialog.show();  
  •             Log.e(TAG, Thread.currentThread().getName() + " onPreExecute ");  
  •         }  
  •   
  •         @Override  
  •         protected Void doInBackground(Void... params)  
  •         {  
  •   
  •             // 模拟数据的加载,耗时的任务  
  •             for (int i = 0; i < 100; i++)  
  •             {  
  •                 try  
  •                 {  
  •                     Thread.sleep(80);  
  •                 } catch (InterruptedException e)  
  •                 {  
  •                     e.printStackTrace();  
  •                 }  
  •                 publishProgress(i);  
  •             }  
  •   
  •             Log.e(TAG, Thread.currentThread().getName() + " doInBackground ");  
  •             return null;  
  •         }  
  •   
  •         @Override  
  •         protected void onProgressUpdate(Integer... values)  
  •         {  
  •             mDialog.setProgress(values[0]);  
  •             Log.e(TAG, Thread.currentThread().getName() + " onProgressUpdate ");  
  •         }  
  •   
  •         @Override  
  •         protected void onPostExecute(Void result)  
  •         {  
  •             // 进行数据加载完成后的UI操作  
  •             mDialog.dismiss();  
  •             mTextView.setText("LOAD DATA SUCCESS ");  
  •             Log.e(TAG, Thread.currentThread().getName() + " onPostExecute ");  
  •         }  
  •     }  
  • }  


进入某个Activity,Activity中需要的数据来自于网络或者其它耗时操作,可以在AsyncTask中onPreExecute完成一些准备操作,比如上例中显示进度对话框;然后在doInBackground完成耗时操作,在进行耗时操作时还能不时的通过publishProgress给onProgressUpdate中传递参数,然后在onProgressUpdate中可以进行UI操作,比如上例更新进度条的进度;当耗时任务执行完成后,最后在onPostExecute进行设置控件数据更新UI等操作,例如隐藏进度对话框。

使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
88#
 楼主| 发表于 2018-3-8 09:04 | 只看该作者

效果图:


3、源码解析注:本篇源码分析基于Andorid-17,因为和3.0之前版本变动较大,有必要标出。

那么大家一定好奇,AsyncTask在Android中是如何实现的,下面进行源码分析:从我们的执行异步任务的起点开始,进入execute方法:http://blog.csdn.net/lmj623565791/article/details/38614699


使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
89#
 楼主| 发表于 2018-3-9 09:22 | 只看该作者
[java] view plain copy


  • public final AsyncTask<Params, Progress, Result> execute(Params... params) {  
  •         return executeOnExecutor(sDefaultExecutor, params);  
  • }  
  • public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,  
  •             Params... params) {  
  •         if (mStatus != Status.PENDING) {  
  •             switch (mStatus) {  
  •                 case RUNNING:  
  •                     throw new IllegalStateException("Cannot execute task:"  
  •                             + " the task is already running.");  
  •                 case FINISHED:  
  •                     throw new IllegalStateException("Cannot execute task:"  
  •                             + " the task has already been executed "  
  •                             + "(a task can be executed only once)");  
  •             }  
  •         }  
  •   
  •         mStatus = Status.RUNNING;  
  •   
  •         onPreExecute();  
  •   
  •         mWorker.mParams = params;  
  •         exec.execute(mFuture);  
  •   
  •         return this;  
  •     }  

18行:设置当前AsyncTask的状态为RUNNING,上面的switch也可以看出,每个异步任务在完成前只能执行一次。
20行:执行了onPreExecute(),当前依然在UI线程,所以我们可以在其中做一些准备工作。
22行:将我们传入的参数赋值给了mWorker.mParams
23行:exec.execute(mFuture)

相信大家对22行出现的mWorker,以及23行出现的mFuture都会有些困惑。
mWorker找到这个类:


[java] view plain copy


  • private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {  
  •         Params[] mParams;  
  • }  


可以看到是Callable的子类,且包含一个mParams用于保存我们传入的参数,下面看初始化mWorker的代码:


[java] view plain copy


  • public AsyncTask() {  
  •         mWorker = new WorkerRunnable<Params, Result>() {  
  •             public Result call() throws Exception {  
  •                 mTaskInvoked.set(true);  
  •   
  •                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
  •                 //noinspection unchecked  
  •                 return postResult(doInBackground(mParams));  
  •             }  
  •         };  
  • //….  
  •          
  • }  


使用道具 举报

回复
论坛徽章:
1682
九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-27 15:37:10九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55九尾狐狸
日期:2012-09-19 11:12:55玉石琵琶
日期:2014-06-26 16:52:29玉石琵琶
日期:2014-06-26 16:52:29
90#
 楼主| 发表于 2018-3-9 09:23 | 只看该作者
可以看到mWorker在构造方法中完成了初始化,并且因为是一个抽象类,在这里new了一个实现类,实现了call方法,call方法中设置mTaskInvoked=true,且最终调用doInBackground(mParams)方法,并返回Result值作为参数给postResult方法.可以看到我们的doInBackground出现了,下面继续看:


[java] view plain copy


  •   private Result postResult(Result result) {  
  •         @SuppressWarnings("unchecked")  
  •         Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,  
  •                 new AsyncTaskResult<Result>(this, result));  
  •         message.sendToTarget();  
  •         return result;  
  • }  


可以看到postResult中出现了我们熟悉的异步消息机制,传递了一个消息message, message.what为MESSAGE_POST_RESULT;message.object= new AsyncTaskResult(this,result);


[java] view plain copy


  • private static class AsyncTaskResult<Data> {  
  •        final AsyncTask mTask;  
  •        final Data[] mData;  
  •   
  •        AsyncTaskResult(AsyncTask task, Data... data) {  
  •            mTask = task;  
  •            mData = data;  
  •        }  
  •    }  


AsyncTaskResult就是一个简单的携带参数的对象。

看到这,我相信大家肯定会想到,在某处肯定存在一个sHandler,且复写了其handleMessage方法等待消息的传入,以及消息的处理。


[java] view plain copy


  • private static final InternalHandler sHandler = new InternalHandler();  
  •     private static class InternalHandler extends Handler {  
  •         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})  
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             AsyncTaskResult result = (AsyncTaskResult) msg.obj;  
  •             switch (msg.what) {  
  •                 case MESSAGE_POST_RESULT:  
  •                     // There is only one result  
  •                     result.mTask.finish(result.mData[0]);  
  •                     break;  
  •                 case MESSAGE_POST_PROGRESS:  
  •                     result.mTask.onProgressUpdate(result.mData);  
  •                     break;  
  •             }  
  •         }  
  • }  



使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表