Android Studio 使用技巧之打造优雅的 Logcat Console

  为此,进行了日志打印一探究竟:

来源

先上一张图吧:

图片 1

QQ截图20170331143254.png

从这个图可以看到, 有些日志1毫秒打印两次, 这是多么恐怖啊,
分分钟终端就满了, pageUp 按键根本跟不上节奏, 导致看不清其他日志,
那我们过滤下呗, 尴尬的是, 包名和我的 APP 一致, 而且 Error 级别,
所以选择 Show only selected application 根本没有效果, 屏幕唰唰而过,
没有一点点防备..

  • 设置布局文件
  • 数据与控件的绑定
  • 控件事件注册

图片 2

图片 3

  • 实现getView(int position, View convertView, ViewGroup parent)方法
  • 数据集合的增删修改,频繁手动调用 notifyDataSetChange()方法

Android Studio 使用技巧之打造优雅的 Logcat Console。这是业务的流程。直接说重点:QCombox在下拉窗更新数据的时候,会默认把下拉窗的第一个条数据,设置为选中的状态,这样的话,就会产生curentTextChanged的一个信号,直接把逻辑层原先有的数据给修改了。

正式拉黑

于是, google 了一下, 提醒各位, 用 google 最好输入 英文关键字, 这样你会
得到 你想要的.

操作很简单:
1: 点击右侧下拉窗, 选择 Edit Filter Configuration,
打开过滤器配置窗口
2: 配置下这个窗口, 如下:

图片 4

QQ截图20170331191455.png

图片里写的还算详细, 包含了基本用途, 相信你看过会打造自己的过滤器,
这样配置后, 终端瞬间清爽很多.

由于Adapter可多个itemType,因此封装的时候缤纷两路,RecyclerAdapter的封装也是如此。

 
 最近项目中开发在用到QCombox,然而在开发中,踩到了一个坑,花了一个晚上,一直在想,好在最后找到问题所在了。

这篇文章主要介绍基于 正则表达式 屏蔽不需要的字符串,
打造更科学的日志终端.

接着上篇,这里想分享ListAdapter、RecyclerView的封装。众所周知,ListAdapter以及RecyclerView都是列表控件,Google更推荐大家使用RecyclerView。关于RecyclerView的基本使用,不在本篇的讨论范围内。

   日志显如下:

参考文章:

https://stackoverflow.com/questions/5511433/how-to-exclude-certain-messages-by-tag-name-using-android-adb-logcat

如何让 Logcat 更美观, 请点击这里:

Android
Studio美化之优雅的logcat

最后,非常感谢您的阅读,有任何疑问,可以后面评论,谢谢!

欢迎加入安卓开发QQ群: 484167109

神奇的安卓开发网站:http://androidcat.com/

安卓开源库收集整理:https://github.com/XXApple/AndroidLibs

分享是一种美德,更是一种生活方式!!

也许你会说我是一个梦想者,但我不是唯一的一个。

悦分享,越快乐_

欢迎交流,转载请注明出处,谢谢!

Step3 事件绑定接口

为了方便事件的统一处理,我抽象了一个抽象类ListItemCallback

 public void onItemClick(int position, T model, int tag) {} //单击 public void onItemLongClick(int position, T model, int tag) {} //长按

参数:

  • position : 就是getView中的position,位置
  • model : 绑定的数据实体
  • tag : 事件标识,自己定义

a. 为什么定义的是抽象类,而不是接口?

因为接口中的方法需要全部实现,而抽象类可以选择性的override,显然,我们通常只需要重写onItemClick方法

b. 如何使用呢?

holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick { if (getCallback() != null) { getCallback().onItemClick(position, item, TAG_VIEW); } } });

c. 为什么我不选择很常见的SparseArray那种封装的CommonAdapter

因为我不喜欢那种编码style,建议将Adapter单独类

RecyclerView的封装一般体现在:

  • 下拉刷新、上拉加载更多
  • header、footer
  • divider

鉴于此,我之前搞了个ARecyclerView,主要有这些特性:

  • ARecyclerView继承自RecyclerView,它就是一个封装了常见功能的RecyclerView,而不是继承FrameLayout
  • ARecyclerView中实现了Header、Footer,header和Footer可以有多个
  • ARecyclerView的每一个header、footer的viewType是不同的,而大部分开源库的header、footer的viewtype是相同的,其直接后果是界面卡顿
  • ARecyclerView可以做出几乎任何的界面效果,可以取代ScrollView,你只需要使用header或者footer
  • ARecyclerView中实现了上拉加载更多,可以自定义加载更多的效果,只需要实现LoadMoreUIHandler接口即可
  • ARecyclerView并未实现下拉刷新功能,您可以选择SwipeRefreshLayout或者其他的下拉刷新viewGroup包裹,即你可以自由选择下拉刷新功能的实现。
  • 为了方便自定义使用,特别集成了XRecyclerContentLayout控件,你可以根据业务进行扩展,XRecyclerContentLayout只是一个示例,当然也可以满足绝大部分需求了

由于其实现相对复杂,推荐大家可以去看看源码,app mudule中是完整的实例

XDroid中,我新增了SimpleRecAdapter,应对单itemType的需求。具体思想和ListAdapter很相似

public abstract class SimpleRecAdapter<T, F extends RecyclerView.ViewHolder> extends RecyclerAdapter<T, F> { public SimpleRecAdapter(Context context) { super; } @Override public F onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext.inflate(getLayoutId(), parent, false); return newViewHolder; } public abstract F newViewHolder(View itemView); public abstract int getLayoutId();}

T 是item的实体类,F是ViewHolder的实体类

下一篇会谈谈ContentLayout的实现过程。

XDroid项目是我在两年的开发中积累的一个Android快速开发框架,目前包含UI层、缓存、图片加载、日志、路由、Api请求、事件订阅、工具类等。下一步会进行mvp、rx全家桶、retrofit、权限适配等工作。欢迎大家提出宝贵意见,指正不足。

最后附上链接:

 Line 151: [D:TalkWindow+13100:10356] 23:05:55.942 101261.059234 getCurrentText 麦克风 (7.1 SOUND EFFECT GAMING HEADSET)
 Line 152: [D:TalkWindow+13100:10356] 23:05:55.943 101261.059569 getCurrentText1 
 Line 155: [D:TalkWindow+13100:10356] 23:05:55.943 101261.060339 getCurrentText2 麦克风 (High Definition Audio 设备)
 Line 156: [D:TalkWindow+13100:10356] 23:05:55.944 101261.060662 getCurrentText3 
 Line 157: [D:TalkWindow+13100:10356] 23:05:55.944 101261.060866 getCurrentText4 
 Line 158: [D:TalkWindow+13100:10356] 23:05:55.944 101261.061036 getCurrentText!!!!! 

在getCurrentText2的日志中,很明显,把additems的数据加载完完,默认选中就变了,然后再执行 setCurrentIndex的时候,把默认选中置为空,也就是说,一共产生了两次 textchange的信号。

解决办法:
  我目前的解决办法是,在获取数据的时候,先断开信号槽的连接,disconnect函数,然后等把下拉窗的数据加载完,再connect函数连接上,这样,加载数据就避免了发送两次信号,修改原有的数据。当然也
可以一个标记bool值,信号发出去的时候,不去处理就好了,但是这样的话,可能不太好控制。所以我选择了前者。有更好的办法,多多指教。

博客: 安卓之家
掘金:
jp1017
微博:
追风917
CSDN:
蒋朋的家
简书:
追风917

转化成代码:

void TalkWindow::getMicList(const QStringList & texts)
{

 DEBUG_TRACE("getCurrentText %s" , m_pDeviceWidget->m_pMicrophoneCombox->currentText().toStdString().c_str());
 if (m_pDeviceWidget == NULL) return;
 m_pDeviceWidget->m_pMicrophoneCombox->clear();
 int a = m_pDeviceWidget->m_pMicrophoneCombox->count();
 m_pDeviceWidget->m_pMicrophoneCombox->setCurrentIndex(-1);
 DEBUG_TRACE("getCurrentText1 %s", m_pDeviceWidget->m_pMicrophoneCombox->currentText().toStdString().c_str());
 m_pDeviceWidget->m_pMicrophoneCombox->addItems(texts);
 DEBUG_TRACE("getCurrentText2 %s", m_pDeviceWidget->m_pMicrophoneCombox->currentText().toStdString().c_str());
 m_pDeviceWidget->m_pMicrophoneCombox->setCurrentIndex(-1);
 m_pDeviceWidget->m_pMicrophoneCombox->insertItem(texts.size()+1, TR_TALK_DEVICE_COMBOX, 0);
 m_pDeviceWidget->m_pMicrophoneCombox->setCurrentIndex(-1);
 DEBUG_TRACE("getCurrentText3 %s", m_pDeviceWidget->m_pMicrophoneCombox->currentText().toStdString().c_str());
 m_pDeviceWidget->m_pMicrophoneCombox->setCurrentIndex(-1);
 DEBUG_TRACE("getCurrentText4 %s", m_pDeviceWidget->m_pMicrophoneCombox->currentText().toStdString().c_str());
 m_pDeviceWidget->m_pMicrophoneCombox->setCurrentIndex(-1);
 DEBUG_TRACE("getCurrentText!!!!! %s", m_pDeviceWidget->m_pMicrophoneCombox->currentText().toStdString().c_str());
}

牛刀小试

不想看到, 就把他拉黑啊

没错, 简单直接, 粗暴高效.

直接在过滤器里面拉黑他, 用正则拉黑, 看起来是这样子:

图片 5

QQ截图20170331185934.png

然而并没有什么卵用, 屏幕刷刷刷依旧. 就差一个千里眼了…

关于 正则表达式, 可以看看这篇文章:

Linux基础之-正则表达式(grep,sed,awk)

之前是排斥 正则表达式 的, 后来发现威力无穷, 于是乎, 以后要好好使用咯.

Step1 封装XListAdapter,作为所有Adapter的基类,子类可实现getView()方法

XListAdapter中主要实现了数据集的增删修改常用操作事件绑定接口
等功能。

+ addData()+ setData()+ clearData+ addElement()+ removeElement()+ getColor()+ getDrawable()+ visible+ invisible()...

来自 Momentum 的美图

 if (convertView == null) { convertView = View.inflate(context, getLayoutId; holder = new ViewHolder(convertView); convertView.setTag; } else { holder = convertView.getTag(); } bindItem(); //绑定数据 setEvent(); //绑定事件 return convertView;

Step2 封装SimpleListAdapter,实现单viewType的需求

核心如下:

 @Override public View getView(int position, View convertView, ViewGroup parent) { H holder = null; T item = data.get; if (convertView == null) { convertView = View.inflate(context, getLayoutId; holder = newViewHolder(convertView); convertView.setTag; } else { holder =  convertView.getTag(); } convert(holder, item, position); return convertView; }

子类则摆脱了这段魔鬼一样的代码,只需要实现这三个方法:

protected abstract H newViewHolder(View convertView); //创建viewHolderprotected abstract int getLayoutId(); //设置布局资源idprotected abstract void convert(H holder, T item, int position); //数据绑定与事件绑定

而在getView()方法中,我们通常会做这么几件事:

ListAdapter作为ListView的数据适配器,为ListView提供数据源。在我们的频繁使用中,发现:对Adapter的编写主要集中在几部分:

网站地图xml地图