网上有不少教程,那个提示框字符集都是事先写好的,例如用一个String[] 数组去包含了这些数据,但是,我们也可以吧用户输入的作为历史记录保存
       下面先上我写的代码:
import android.app.Activity;

  1. import android.content.SharedPreferences;
  2. import android.os.Bundle;
  3. import android.util.Log;
  4. import android.view.View;
  5. import android.view.View.OnClickListener;
  6. import android.view.View.OnFocusChangeListener;
  7. import android.widget.ArrayAdapter;
  8. import android.widget.AutoCompleteTextView;
  9. import android.widget.Button;
  10. public class Read_historyActivity extends Activity implements
  11. OnClickListener {
  12. private AutoCompleteTextView autoTv;
  13. /** Called when the activity is first created. */
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. autoTv = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
  19. initAutoComplete("history",autoTv);
  20. Button search = (Button) findViewById(R.id.button1);
  21. search.setOnClickListener(this);
  22. }
  23. @Override
  24. public void onClick(View v) {
  25. // 这里可以设定:当搜索成功时,才执行保存操作
  26. saveHistory("history",autoTv);
  27. }
  28. /**
  29. * 初始化AutoCompleteTextView,最多显示5项提示,使
  30. * AutoCompleteTextView在一开始获得焦点时自动提示
  31. * @param field 保存在sharedPreference中的字段名
  32. * @param auto 要操作的AutoCompleteTextView
  33. */
  34. private void initAutoComplete(String field,AutoCompleteTextView auto) {
  35. SharedPreferences sp = getSharedPreferences("network_url", 0);
  36. String longhistory = sp.getString("history", "nothing");
  37. String[]  hisArrays = longhistory.split(",");
  38. ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
  39. android.R.layout.simple_dropdown_item_1line, hisArrays);
  40. //只保留最近的50条的记录
  41. if(hisArrays.length > 50){
  42. String[] newArrays = new String[50];
  43. System.arraycopy(hisArrays, 0, newArrays, 0, 50);
  44. adapter = new ArrayAdapter<String>(this,
  45. android.R.layout.simple_dropdown_item_1line, newArrays);
  46. }
  47. auto.setAdapter(adapter);
  48. auto.setDropDownHeight(350);
  49. auto.setThreshold(1);
  50. auto.setCompletionHint("最近的5条记录");
  51. auto.setOnFocusChangeListener(new OnFocusChangeListener() {
  52. @Override
  53. public void onFocusChange(View v, boolean hasFocus) {
  54. AutoCompleteTextView view = (AutoCompleteTextView) v;
  55. if (hasFocus) {
  56. view.showDropDown();
  57. }
  58. }
  59. });
  60. }
  61. /**
  62. * 把指定AutoCompleteTextView中内容保存到sharedPreference中指定的字符段
  63. * @param field  保存在sharedPreference中的字段名
  64. * @param auto  要操作的AutoCompleteTextView
  65. */
  66. private void saveHistory(String field,AutoCompleteTextView auto) {
  67. String text = auto.getText().toString();
  68. SharedPreferences sp = getSharedPreferences("network_url", 0);
  69. String longhistory = sp.getString(field, "nothing");
  70. if (!longhistory.contains(text + ",")) {
  71. StringBuilder sb = new StringBuilder(longhistory);
  72. sb.insert(0, text + ",");
  73. sp.edit().putString("history", sb.toString()).commit();
  74. }
  75. <span style="font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240); "> }
  76. }</span>

上面的代码我实现了autocomplettextview的从sharepreference中读取历史记录并显示的功能,当没有任何输入时,提示最新的5项历史记录(这里可以加个条件,当有历史记录时才显示)
              补上布局的代码

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:orientation="vertical"
  5. android:layout_width="fill_parent"
  6. android:layout_height="fill_parent">
  7. <TextView android:layout_width="fill_parent"
  8. android:layout_height="wrap_content"
  9. android:text="@string/hello" />
  10. <LinearLayout android:layout_width="0px"
  11. android:layout_height="0px" android:focusable="true"
  12. android:focusableInTouchMode="true"></LinearLayout>
  13. <AutoCompleteTextView
  14. android:hint="请输入文字进行搜索" android:layout_height="wrap_content"
  15. android:layout_width="match_parent"
  16. android:id="@+id/autoCompleteTextView1">
  17. </AutoCompleteTextView>
  18. <Button android:text="搜索" android:id="@+id/button1"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"></Button>
  21. </LinearLayout>

当之有一个edittext或者auto的时候,进入画面时是默认得到焦点的,要想去除焦点,可以在auto之前加一个o像素的layout,并设置他先得到焦点。

效果图如下

下面出现的是源码内容 
               需要注意的是,我这里用到的AutoCompleteTextView的几个方法
               1. setAdapter()方法:这里要传递的adapter参数必须是继承ListAdapter和Filterable的,其中arrayAdapter和simpleAdapter都能满足要求,我们常用arrayAdapter,因为他不需要像simpleAdapte那样设置他的显示位置和textview组件。
               要想掌握它,就必须查看他的源码,我们可以看看arrayadapter是如何实现
              凡是继承了Filterable的adapter都必须重写getFilter接口方法

  1. public Filter getFilter() {
  2. if (mFilter == null) {
  3. mFilter = new ArrayFilter();
  4. }
  5. return mFilter;
  6. }

这个filter 就是实现过滤方法的对象,同样,我们可以查看他的源码是如何实现的

  1. /**
  2. * <p>An array filter constrains the content of the array adapter with
  3. * a prefix. Each item that does not start with the supplied prefix
  4. * is removed from the list.</p>
  5. */
  6. private class ArrayFilter extends Filter {
  7. @Override
  8. protected FilterResults performFiltering(CharSequence prefix) {
  9. FilterResults results = new FilterResults();
  10. if (mOriginalValues == null) {
  11. synchronized (mLock) {
  12. mOriginalValues = new ArrayList<T>(mObjects);
  13. }
  14. }
  15. if (prefix == null || prefix.length() == 0) {
  16. synchronized (mLock) {
  17. ArrayList<T> list = new ArrayList<T>(mOriginalValues);
  18. results.values = list;
  19. results.count = list.size();
  20. }
  21. } else {
  22. String prefixString = prefix.toString().toLowerCase();
  23. final ArrayList<T> values = mOriginalValues;
  24. final int count = values.size();
  25. final ArrayList<T> newValues = new ArrayList<T>(count);
  26. for (int i = 0; i < count; i++) {
  27. final T value = values.get(i);
  28. final String valueText = value.toString().toLowerCase();
  29. // First match against the whole, non-splitted value
  30. if (valueText.startsWith(prefixString)) {
  31. newValues.add(value);
  32. } else {
  33. final String[] words = valueText.split(" ");
  34. final int wordCount = words.length;
  35. for (int k = 0; k < wordCount; k++) {
  36. if (words[k].startsWith(prefixString)) {
  37. newValues.add(value);
  38. break;
  39. }
  40. }
  41. }
  42. }
  43. results.values = newValues;
  44. results.count = newValues.size();
  45. }
  46. return results;
  47. }

这是arrayAdapter自定义的一个私有内部类,所谓私有,就意味着你不能通过继承去修改这种过滤方法,同样你也不能直接得到他过滤后结果集results。假如你想使用新的过滤方法,你必须重写getfilter()方法,返回的filter对象是你要新建的filter对象(在里面包含performFiltering()方法重新构造你要的过滤方法)
          
         2.setDropDownHeight方法 ,用来设置提示下拉框的高度,注意,这只是限制了提示下拉框的高度,提示数据集的个数并没有变化
         3.setThreshold方法,设置从输入第几个字符起出现提示
         4.setCompletionHint方法,设置提示框最下面显示的文字
         5.setOnFocusChangeListener方法,里面包含OnFocusChangeListener监听器,设置焦点改变事件
         6.showdropdown方法,让下拉框弹出来

我没有用到的一些方法列举
1.clearListSelection,去除selector样式,只是暂时的去除,当用户再输入时又重新出现
2.dismissDropDown,关闭下拉提示框
3.enoughToFilter,这是一个是否满足过滤条件的方法,sdk建议我们可以重写这个方法
4. getAdapter,得到一个可过滤的列表适配器
5.getDropDownAnchor,得到下拉框的锚计的view的id
6.getDropDownBackground,得到下拉框的背景色
7.setDropDownBackgroundDrawable,设置下拉框的背景色
8.setDropDownBackgroundResource,设置下拉框的背景资源
9.setDropDownVerticalOffset,设置下拉表垂直偏移量,即是list里包含的数据项数目
10.getDropDownVerticalOffset ,得到下拉表垂直偏移量
11..setDropDownHorizontalOffset,设置水平偏移量
12.setDropDownAnimationStyle,设置下拉框的弹出动画
13.getThreshold,得到过滤字符个数
14.setOnItemClickListener,设置下拉框点击事件
15.getListSelection,得到下拉框选中为位置
16.getOnItemClickListener。得到单项点击事件
17.getOnItemSelectedListener得到单项选中事件
18.getAdapter,得到那个设置的适配器

一些隐藏方法和构造我没有列举了,具体可以参考api文档 
可下载我的写的demo: http://download.csdn.net/detail/iamkila/4042528

自定义:

网上找到的都是同ArrayAdapter一起使用的,有时候需要自定义风格,咋办?follow me!

 
看上图,实现了清空输入框内容和删除Item功能。

其实使用AutoCompleteTextView就得实现过滤器Filterable,你得告诉它怎么过滤。由于ArrayAdapter已经帮我们实现了Filterable接口,所以我们很容易忽略这个,以为AutoCompleteTextView用起来很简单。如果你使用的是BaseAdapter呢?当然,事实上也不难,只要让它也实现Filterable接口就可以了。

下面是源码: 
实现自定义的Adapter

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import qianlong.qlmobile.tablet.csco.R;
  4. import android.content.Context;
  5. import android.util.Log;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.view.View.OnClickListener;
  10. import android.widget.BaseAdapter;
  11. import android.widget.Filter;
  12. import android.widget.Filterable;
  13. import android.widget.ImageView;
  14. import android.widget.TextView;
  15. public class AutoCompleteAdapter extends BaseAdapter implements Filterable{
  16. private Context context;
  17. private ArrayFilter mFilter;
  18. private ArrayList<String> mOriginalValues;//所有的Item
  19. private List<String> mObjects;//过滤后的item
  20. private final Object mLock = new Object();
  21. private int maxMatch=10;//最多显示多少个选项,负数表示全部
  22. public AutoCompleteAdapter(Context context,ArrayList<String> mOriginalValues,int maxMatch){
  23. this.context=context;
  24. this.mOriginalValues=mOriginalValues;
  25. this.maxMatch=maxMatch;
  26. }
  27. @Override
  28. public Filter getFilter() {
  29. // TODO Auto-generated method stub
  30. if (mFilter == null) {
  31. mFilter = new ArrayFilter();
  32. }
  33. return mFilter;
  34. }
  35. private class ArrayFilter extends Filter {
  36. @Override
  37. protected FilterResults performFiltering(CharSequence prefix) {
  38. // TODO Auto-generated method stub
  39. FilterResults results = new FilterResults();
  40. //          if (mOriginalValues == null) {
  41. //                synchronized (mLock) {
  42. //                    mOriginalValues = new ArrayList<String>(mObjects);//
  43. //                }
  44. //            }
  45. if (prefix == null || prefix.length() == 0) {
  46. synchronized (mLock) {
  47. Log.i("tag", "mOriginalValues.size="+mOriginalValues.size());
  48. ArrayList<String> list = new ArrayList<String>(mOriginalValues);
  49. results.values = list;
  50. results.count = list.size();
  51. return results;
  52. }
  53. } else {
  54. String prefixString = prefix.toString().toLowerCase();
  55. final int count = mOriginalValues.size();
  56. final ArrayList<String> newValues = new ArrayList<String>(count);
  57. for (int i = 0; i < count; i++) {
  58. final String value = mOriginalValues.get(i);
  59. final String valueText = value.toLowerCase();
  60. //                    if(valueText.contains(prefixString)){//匹配所有
  61. //
  62. //                    }
  63. // First match against the whole, non-splitted value
  64. if (valueText.startsWith(prefixString)) {  //源码 ,匹配开头
  65. newValues.add(value);
  66. }
  67. //                    else {
  68. //                        final String[] words = valueText.split(" ");//分隔符匹配,效率低
  69. //                        final int wordCount = words.length;
  70. //
  71. //                        for (int k = 0; k < wordCount; k++) {
  72. //                            if (words[k].startsWith(prefixString)) {
  73. //                                newValues.add(value);
  74. //                                break;
  75. //                            }
  76. //                        }
  77. //                    }
  78. if(maxMatch>0){//有数量限制
  79. if(newValues.size()>maxMatch-1){//不要太多
  80. break;
  81. }
  82. }
  83. }
  84. results.values = newValues;
  85. results.count = newValues.size();
  86. }
  87. return results;
  88. }
  89. @Override
  90. protected void publishResults(CharSequence constraint,
  91. FilterResults results) {
  92. // TODO Auto-generated method stub
  93. mObjects = (List<String>) results.values;
  94. if (results.count > 0) {
  95. notifyDataSetChanged();
  96. } else {
  97. notifyDataSetInvalidated();
  98. }
  99. }
  100. }
  101. @Override
  102. public int getCount() {
  103. // TODO Auto-generated method stub
  104. return mObjects.size();
  105. }
  106. @Override
  107. public Object getItem(int position) {
  108. // TODO Auto-generated method stub
  109. //此方法有误,尽量不要使用
  110. return mObjects.get(position);
  111. }
  112. @Override
  113. public long getItemId(int position) {
  114. // TODO Auto-generated method stub
  115. return position;
  116. }
  117. @Override
  118. public View getView(final int position, View convertView, ViewGroup parent) {
  119. // TODO Auto-generated method stub
  120. ViewHolder holder = null;
  121. if(convertView==null){
  122. holder=new ViewHolder();
  123. LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  124. convertView=inflater.inflate(R.layout.simple_list_item_for_autocomplete, null);
  125. holder.tv=(TextView)convertView.findViewById(R.id.simple_item_0);
  126. holder.iv=(ImageView)convertView.findViewById(R.id.simple_item_1);
  127. convertView.setTag(holder);
  128. }else{
  129. holder = (ViewHolder) convertView.getTag();
  130. }
  131. holder.tv.setText(mObjects.get(position));
  132. holder.iv.setOnClickListener(new OnClickListener() {
  133. @Override
  134. public void onClick(View v) {
  135. // TODO Auto-generated method stub
  136. String obj=mObjects.remove(position);
  137. mOriginalValues.remove(obj);
  138. notifyDataSetChanged();
  139. }
  140. });
  141. return convertView;
  142. }
  143. class ViewHolder {
  144. TextView tv;
  145. ImageView iv;
  146. }
  147. public ArrayList<String> getAllItems(){
  148. return mOriginalValues;
  149. }
  150. }
  1. import android.content.Context;
  2. import android.util.AttributeSet;
  3. import android.view.View;
  4. import android.widget.AutoCompleteTextView;
  5. import android.widget.ImageView;
  6. import android.widget.RelativeLayout;
  7. import android.widget.ImageView.ScaleType;
  8. public class AdvancedAutoCompleteTextView extends RelativeLayout{
  9. private Context context;
  10. private AutoCompleteTextView tv;
  11. public AdvancedAutoCompleteTextView(Context context) {
  12. super(context);
  13. // TODO Auto-generated constructor stub
  14. this.context=context;
  15. }
  16. public AdvancedAutoCompleteTextView(Context context, AttributeSet attrs) {
  17. super(context, attrs);
  18. // TODO Auto-generated constructor stub
  19. this.context=context;
  20. }
  21. @Override
  22. protected void onFinishInflate() {
  23. super.onFinishInflate();
  24. initViews();
  25. }
  26. private void initViews() {
  27. RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
  28. tv=new AutoCompleteTextView(context);
  29. tv.setLayoutParams(params);
  30. tv.setPadding(10, 0, 40, 0);
  31. //      tv.setSingleLine(true);
  32. RelativeLayout.LayoutParams p=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
  33. p.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
  34. p.addRule(RelativeLayout.CENTER_VERTICAL);
  35. p.rightMargin=10;
  36. ImageView iv=new ImageView(context);
  37. iv.setLayoutParams(p);
  38. iv.setScaleType(ScaleType.FIT_CENTER);
  39. iv.setImageResource(R.drawable.delete);
  40. iv.setClickable(true);
  41. iv.setOnClickListener(new View.OnClickListener() {
  42. @Override
  43. public void onClick(View v) {
  44. // TODO Auto-generated method stub
  45. tv.setText("");
  46. }
  47. });
  48. this.addView(tv);
  49. this.addView(iv);
  50. }
  51. public void setAdapter(AutoCompleteAdapter adapter){
  52. tv.setAdapter(adapter);
  53. }
  54. public void setThreshold(int threshold){
  55. tv.setThreshold(threshold);
  56. }
  57. public AutoCompleteTextView getAutoCompleteTextView(){
  58. return tv;
  59. }
  60. }

simple_list_item_for_autocomplete.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="wrap_content"
  5. android:orientation="horizontal"
  6. android:paddingTop="5dip"
  7. android:paddingBottom="5dip"
  8. >
  9. <TextView android:id="@+id/simple_item_0"
  10. android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"
  12. android:layout_weight="1"
  13. android:paddingLeft="5dip"
  14. android:textColor="@android:color/black"
  15. />
  16. <ImageView android:id="@+id/simple_item_1"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:scaleType="fitCenter"
  20. android:src="@drawable/delete"
  21. android:layout_centerVertical="true"
  22. android:layout_marginRight="5dip"
  23. />
  24. </LinearLayout>

使用,通常情况下都这样:

    1. private AdvancedAutoCompleteTextView tv;
    2. private AutoCompleteAdapter adapter;
    3. private ArrayList<String> mOriginalValues=new ArrayList<String>();
    4. @Override
    5. public void onCreate(Bundle savedInstanceState) {
    6. super.onCreate(savedInstanceState);
    7. setContentView(R.layout.main);
    8. mOriginalValues.add("1234561");
    9. mOriginalValues.add("1234562");
    10. mOriginalValues.add("2234563");
    11. mOriginalValues.add("2234564");
    12. mOriginalValues.add("3234561111");
    13. mOriginalValues.add("32345622222");
    14. mOriginalValues.add("323456333333");
    15. mOriginalValues.add("3234564444");
    16. mOriginalValues.add("3234565555");
    17. mOriginalValues.add("32345666666");
    18. mOriginalValues.add("32345777777");
    19. tv = (AdvancedAutoCompleteTextView) findViewById(R.id.tv);
    20. tv.setThreshold(0);
    21. adapter = new AutoCompleteAdapter(this, mOriginalValues, 10);
    22. tv.setAdapter(adapter);
    23. }
    24. http://gundumw100.iteye.com/blog/1446507

AutoCompleteTextView 简单用法 实现自定义list adapter的更多相关文章

  1. AutoCompleteTextView 简单用法

    http://blog.csdn.net/i_lovefish/article/details/17337999

  2. 转载 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

    转载自:http://www.cnblogs.com/cj695/p/3863142.html sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在 ...

  3. 【转】 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

    sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能 ...

  4. 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

    sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能 ...

  5. 【C++】从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

    sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能 ...

  6. Android MultiType第三方库的基本使用和案例+DiffUtil的简单用法

    1.MultiType简单介绍 1.1.MultiType用于比较复杂的页面. 如下图,今日头条用到了MultiType处理各种复杂的页面.    这种还是比较简单的类型.因为一个页面也就这种类型. ...

  7. Android—— ListView 的简单用法及定制ListView界面

    一.ListView的简单用法 2. 训练目标 1) 掌握 ListView 控件的使用 2) 掌握 Adapter 桥梁的作用 实现步骤: 1)首先新建一个项目, 并让ADT 自动帮我们创建好活动. ...

  8. listActivity和ExpandableListActivity的简单用法

    http://www.cnblogs.com/limingblogs/archive/2011/10/09/2204866.html 今天自己简单的总结了listActivity和Expandable ...

  9. SQL*Plus break与compute的简单用法

    SQL*Plus break与compute的简单用法在SQL*Plus提示符下输出求和报表,我们可以借助break与compute两个命令来实现.这个两个命令简单易用,可满足日常需求,其实质也相当于 ...

随机推荐

  1. Linux安装middleBox之prads

    PRADS prads github安装 prads github 项目 prads github命令

  2. 记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)

    0x01 前言 最近在做代码审计的工作中遇到了一个难题,题目描述如下: <?php include 'flag.php'; if(isset($_GET['code'])){ $code = $ ...

  3. zabbix监控主机cpu达到80%后报警

    在zabbix监控中,默认cpu监控模板中的触发器,当负载在一定时间内(比如最近5分钟)超过5以上为报警阀值.但是在实际场景中,由于服务器配置不一样,这个默认的cpu触发器用起来意义就不大了,这时候就 ...

  4. 安装Visual Studio开发平台

    1.找一个VS2013的安装包,下载到D盘上,勾选相应的选项安装. 安装的过程很漫长,至少需要一个小时. 2.安装已完成,启动. . 3.登录. \ 4启动VS2013. 5.新建c#类库 6.输入代 ...

  5. SCRUM 12.21

    从爬虫遇到的问题中我们学会了: 1.有的网站是有反爬虫机制的,外卖网站(我们猜测基本所有盈利性质的网站可能都是)全部都有. 2.我们对于反爬虫机制有了一定的了解.   本次爬虫测试中,我们最后连美团网 ...

  6. linux内核分析第七次实验

    实验: rm menu -rf git clone https://github.com/megnning/menu.git cd menu ls mv test_exec.c test.c vi t ...

  7. spring中通过JNDI、DBCP、C3P0配置数据源

    JNDI配置数据源 1.首先在tomcat的server.xml中配置数据源信息,找到Context,然后在里边加入如下代码 <Context docBase="SpringDemo& ...

  8. QQ通信机制(转)

    下面有4个基本的问答: 问题一:为什么只要可以连上互联网的计算机都可以用QQ相互建立通信,而不需要固定IP?也就是这个QQ用户端是怎样找到另一个QQ用户的,而用户在每次使用时他可能用的是不同的计算机, ...

  9. shiro课程的学习

    1.shiro的课程目标 (1)shiro的整体框架 各组件的概念 (2)shiro 认证 授权的过程 (3)shiro自定义的Reaml Filter (4)shiro session 管理 (5) ...

  10. 小学四则运算APP 第三阶段冲刺

    <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android=" ...