消灭模板代码,自定义AndroidStudio文件模板

Posted TellH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消灭模板代码,自定义AndroidStudio文件模板相关的知识,希望对你有一定的参考价值。

Previously

我们日常开发肯定会或多或少遇到写模板代码的时候,比如写Adapter、写单例类、写用Parcelable实现序列化的相关代码、写实现Mvp架构的相关接口等等。但作为一个追求优雅编码的人,我一直崇尚“Write the code you have to write ”,快速高效地开发。这系列文章将分享如何将androidStudio打造成消灭模板代码的利器。

照葫芦画瓢

当我们在工程中右键->New ,一般都有一个Singleton的菜单项。

填写了文件名后会生成一个.java文件,上面已经写有实现简单单例的代码:

public class Sample
    private static my uniqueInstance = new my();
    public static Sample getInstance() 
        return uniqueInstance;
    
    private Sample() 
    

还不错,但能不能修改这个单例模板,甚至添加自定义模板呢?
眼尖的童鞋已经发现Singleton菜单项下还有一个Edit File Templates的菜单项,点进去一探究竟。

代码模板就在上面,与生成的代码对照一下很快就能明白。

  • 前两句是必加的
#if ($PACKAGE_NAME && $PACKAGE_NAME != "")package $PACKAGE_NAME;#end
#parse("File Header.java")
  • $NAME是模板文件接受的输入变量,特指输入的类名。
  • $ 组合符号添加一个自定义的输入变量。这些输入变量是在生成文件前由用户输入的。
  • 在生成代码时,这些输入变量会对号入座,填充拼接到代码中。

这个单例模板有点简单,我想将它改成线程安全的单例,那么我们可以将模板改成这样:

#if ($PACKAGE_NAME && $PACKAGE_NAME != "")package $PACKAGE_NAME;#end
#parse("File Header.java")
public class $NAME
    private volatile static $NAME uniqueInstance ;

    public static $NAME getInstance() 
        if (uniqueInstance == null)
            synchronized ($NAME.class)
                if (uniqueInstance!=null)
                    uniqueInstance=new $NAME();
            
        
        return uniqueInstance;
    
    private $NAME() 
 

这样,模板就改成了一个我们想要的线程安全的单例了,不信你试试?

实践出真知

几乎每个Android工程都离不开写大量的Adapter,利用AndroidStudio生成Adapter模板可以让我们节省80%的代码,更专注于业务逻辑的代码上。
编写Adapter是一个比较模板化的工作,输入变量大概有:Adapter类名、Data List的泛型类型还有item的Layout ID,以上这个变量,分别用$NAME$item_type$layout_id 的符号表示。
完整代码模板如下:

#if ($PACKAGE_NAME && $PACKAGE_NAME != "")package $PACKAGE_NAME;#end

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;

#parse("File Header.java")
public class $NAMEAdapter extends RecyclerView.Adapter<$NAMEAdapter.ViewHolder> 
    private final Context context;
    private List<$item_type> items;

    public $NAMEAdapter(List<$item_type> items, Context context) 
        this.items = items;
        this.context = context;
    

    @Override
    public $NAMEAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                             int viewType) 
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.$layout_id, parent, false);
        return new $NAMEAdapter.ViewHolder(v);
    

    @Override
    public void onBindViewHolder($NAMEAdapter.ViewHolder holder, int position) 
        $item_type item = items.get(position);
        //TODO Fill in your logic for binding the view.
    

    @Override
    public int getItemCount() 
        if (items == null)
            return 0;
        
        return items.size();
    
    public static class ViewHolder extends RecyclerView.ViewHolder
    public View rootView;
    public ViewHolder(View rootView) 
            super(rootView);
            this.rootView = rootView;
        
    

下面点击编辑模板对话框左上角的加号:

将模板代码copy到上面,记得为模板添加一个帅气的名字,然后点击OK。
这样自定义的Adapter文件模板成功添加到AndroidStudio中,赶紧试一试吧。

这个对话框输入的变量就对应着我们模板中的三个变量。

当然这是RecyclerView的Adapter,你还可以自己动手写一个ListView的Adapter哦。
顺便,我也分享一下我的ListView Adapter,供大家参考:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.Collections;
import java.util.List;

public class $NAMEAdapter extends BaseAdapter 
    private final Context context;
    private List<$ITEM_TYPE> items;
    private LayoutInflater layoutInflater;

    public $NAMEAdapter (Context context, List<$ITEM_TYPE> items) 
        this.context = context;
        if (items == null)
            items = Collections.emptyList();
        this.items = items;
        layoutInflater = LayoutInflater.from(context);
    

    @Override
    public int getCount() 
        if (items == null) 
            return 0;
        
        return items.size();
    

    @Override
    public Object getItem(int position) 
        return items.get(position);
    

    @Override
    public long getItemId(int position) 
        return R.layout.$ITEM_LAYOUT;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        final ViewHolder holder;
        View view;
        if (convertView == null) 
            view = layoutInflater.inflate(R.layout.$ITEM_LAYOUT, parent, false);
            holder = new ViewHolder(view);
            view.setTag(holder);
         else 
            view = convertView;
            holder = (ViewHolder) view.getTag();
        
        onBindView(position, holder, items.get(position));
        return view;
    

    private void onBindView(int position, ViewHolder holder, $ITEM_TYPE item) 

    

    public static class ViewHolder 
        public View rootView;

        public ViewHolder(View rootView) 
            this.rootView = rootView;
        
    

Summary

通过自定义文件模板,写一个Adapter,只需要写item的数据填充和事件绑定就可以了,很爽是吧。还有,我们可以添加一些模板快速生成BaseActivity,Application,甚至是dagger中的AppModule和AppComponent等等。结束前挖一个坑:这种方法虽然简单,但不能一次性生成一组文件。比如说,我不想生成一个个有大量重复代码的Adapter,而是想一次性生成一个封装过的BaseAdapter和一个继承这个BaseAdapter的Adapter类,这也比较符合我们平时的编码习惯,自定义的Adapter也更干净。那么应该怎么做呢,敬请期待下一篇文章。

参考文章:
How to make your own File Templates in Android Studio – Part 1

以上是关于消灭模板代码,自定义AndroidStudio文件模板的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio自定义注释模板

android:如何通过自定义工程模板让新建的工程都默认支持lambda表达式

Android Studio 配置快速生成模板代码

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段2——.vue文件的模板

一些提高Android开发效率的经验和技巧