搜索
首页php教程php手册Android字符串格式化开源库phrase介绍

Android字符串格式化开源库phrase介绍

在上一篇博客Android通过String.format格式化(动态改变)字符串资源的显示内容中介绍了通过String.format来格式化string.xml文件中的字符串,本文介绍一个可以实现同样功能的开源库phrase,相比于String.format,通过phrase格式化字符串代码更具可读性。


一、phrase项目介绍:

1、源码:phrase项目的源代码很简单,里面总共只有一个类:Phrase.java,代码如下:

/*
 * Copyright (C) 2013 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.uperone.stringformat;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import android.app.Fragment;
import android.content.Context;
import android.content.res.Resources;
import android.text.SpannableStringBuilder;
import android.view.View;

/**
 * A fluent API for formatting Strings. Canonical usage:
 * <pre class="code">
 *   CharSequence formatted = Phrase.from("Hi {first_name}, you are {age} years old.")
 *       .put("first_name", firstName)
 *       .put("age", age)
 *       .format();
 * 
*
    *
  • Surround keys with curly braces; use two {{ to escape.
  • *
  • Keys start with lowercase letters followed by lowercase letters and underscores.
  • *
  • Spans are preserved, such as simple HTML tags found in strings.xml.
  • *
  • Fails fast on any mismatched keys.
  • *
* The constructor parses the original pattern into a doubly-linked list of {@link Token}s. * These tokens do not modify the original pattern, thus preserving any spans. *

* The {@link #format()} method iterates over the tokens, replacing text as it iterates. The * doubly-linked list allows each token to ask its predecessor for the expanded length. */ public final class Phrase { /** The unmodified original pattern. */ private final CharSequence pattern; /** All keys parsed from the original pattern, sans braces. */ private final Set keys = new HashSet(); private final Map keysToValues = new HashMap(); /** Cached result after replacing all keys with corresponding values. */ private CharSequence formatted; /** The constructor parses the original pattern into this doubly-linked list of tokens. */ private Token head; /** When parsing, this is the current character. */ private char curChar; private int curCharIndex; /** Indicates parsing is complete. */ private static final int EOF = 0; /** * Entry point into this API. * * @throws IllegalArgumentException if pattern contains any syntax errors. */ public static Phrase from(Fragment f, int patternResourceId) { return from(f.getResources(), patternResourceId); } /** * Entry point into this API. * * @throws IllegalArgumentException if pattern contains any syntax errors. */ public static Phrase from(View v, int patternResourceId) { return from(v.getResources(), patternResourceId); } /** * Entry point into this API. * * @throws IllegalArgumentException if pattern contains any syntax errors. */ public static Phrase from(Context c, int patternResourceId) { return from(c.getResources(), patternResourceId); } /** * Entry point into this API. * * @throws IllegalArgumentException if pattern contains any syntax errors. */ public static Phrase from(Resources r, int patternResourceId) { return from(r.getText(patternResourceId)); } /** * Entry point into this API; pattern must be non-null. * * @throws IllegalArgumentException if pattern contains any syntax errors. */ public static Phrase from(CharSequence pattern) { return new Phrase(pattern); } /** * Replaces the given key with a non-null value. You may reuse Phrase instances and replace * keys with new values. * * @throws IllegalArgumentException if the key is not in the pattern. */ public Phrase put(String key, CharSequence value) { if (!keys.contains(key)) { throw new IllegalArgumentException("Invalid key: " + key); } if (value == null) { throw new IllegalArgumentException("Null value for '" + key + "'"); } keysToValues.put(key, value); // Invalidate the cached formatted text. formatted = null; return this; } /** @see #put(String, CharSequence) */ public Phrase put(String key, int value) { if (!keys.contains(key)) { throw new IllegalArgumentException("Invalid key: " + key); } keysToValues.put(key, Integer.toString(value)); // Invalidate the cached formatted text. formatted = null; return this; } /** * Silently ignored if the key is not in the pattern. * * @see #put(String, CharSequence) */ public Phrase putOptional(String key, CharSequence value) { return keys.contains(key) ? put(key, value) : this; } /** @see #put(String, CharSequence) */ public Phrase putOptional(String key, int value) { return keys.contains(key) ? put(key, value) : this; } /** * Returns the text after replacing all keys with values. * * @throws IllegalArgumentException if any keys are not replaced. */ public CharSequence format() { if (formatted == null) { if (!keysToValues.keySet().containsAll(keys)) { Set missingKeys = new HashSet(keys); missingKeys.removeAll(keysToValues.keySet()); throw new IllegalArgumentException("Missing keys: " + missingKeys); } // Copy the original pattern to preserve all spans, such as bold, italic, etc. SpannableStringBuilder sb = new SpannableStringBuilder(pattern); for (Token t = head; t != null; t = t.next) { t.expand(sb, keysToValues); } formatted = sb; } return formatted; } /** * Returns the raw pattern without expanding keys; only useful for debugging. Does not pass * through to {@link #format()} because doing so would drop all spans. */ @Override public String toString() { return pattern.toString(); } private Phrase(CharSequence pattern) { curChar = (pattern.length() > 0) ? pattern.charAt(0) : EOF; this.pattern = pattern; // A hand-coded lexer based on the idioms in "Building Recognizers By Hand". // http://www.antlr2.org/book/byhand.pdf. Token prev = null; Token next; while ((next = token(prev)) != null) { // Creates a doubly-linked list of tokens starting with head. if (head == null) head = next; prev = next; } } /** Returns the next token from the input pattern, or null when finished parsing. */ private Token token(Token prev) { if (curChar == EOF) { return null; } if (curChar == '{') { char nextChar = lookahead(); if (nextChar == '{') { return leftCurlyBracket(prev); } else if (nextChar >= 'a' && nextChar = 'a' && curChar data); /** Returns the number of characters after expansion. */ abstract int getFormattedLength(); /** Returns the character index after expansion. */ final int getFormattedStart() { if (prev == null) { // The first token. return 0; } else { // Recursively ask the predecessor node for the starting index. return prev.getFormattedStart() + prev.getFormattedLength(); } } } /** Ordinary text between tokens. */ private static class TextToken extends Token { private final int textLength; TextToken(Token prev, int textLength) { super(prev); this.textLength = textLength; } @Override void expand(SpannableStringBuilder target, Map data) { // Don't alter spans in the target. } @Override int getFormattedLength() { return textLength; } } /** A sequence of two curly brackets. */ private static class LeftCurlyBracketToken extends Token { LeftCurlyBracketToken(Token prev) { super(prev); } @Override void expand(SpannableStringBuilder target, Map data) { int start = getFormattedStart(); target.replace(start, start + 2, "{"); } @Override int getFormattedLength() { // Replace {{ with {. return 1; } } private static class KeyToken extends Token { /** The key without { and }. */ private final String key; private CharSequence value; KeyToken(Token prev, String key) { super(prev); this.key = key; } @Override void expand(SpannableStringBuilder target, Map data) { value = data.get(key); int replaceFrom = getFormattedStart(); // Add 2 to account for the opening and closing brackets. int replaceTo = replaceFrom + key.length() + 2; target.replace(replaceFrom, replaceTo, value); } @Override int getFormattedLength() { // Note that value is only present after expand. Don't error check because this is all // private code. return value.length(); } } }


2、字符串格式化原理:

通过阅读Phrase.java的代码可知,它用"{"和"}"将需要格式化的内容包起来,然后用键值对给需要改变的内容传值,包起来的内容为键,值为动态设置的内容,比如:

"Hi {first_name}, you are {age} years old."
我们要最终的显示内容为:“Hi UperOne, you are 26 years old.”这里的first_name和age是键,值为UperOne和26。


二、使用方法:

Phrase.java的类名上面的注释已经告诉了我们具体的使用方法:

/**
 * A fluent API for formatting Strings. Canonical usage:
 * 
 *   CharSequence formatted = Phrase.from("Hi {first_name}, you are {age} years old.")
 *       .put("first_name", firstName)
 *       .put("age", age)
 *       .format();
 * 
*
    *
  • Surround keys with curly braces; use two {{ to escape.
  • *
  • Keys start with lowercase letters followed by lowercase letters and underscores.
  • *
  • Spans are preserved, such as simple HTML tags found in strings.xml.
  • *
  • Fails fast on any mismatched keys.
  • *
* The constructor parses the original pattern into a doubly-linked list of {@link Token}s. * These tokens do not modify the original pattern, thus preserving any spans. *

* The {@link #format()} method iterates over the tokens, replacing text as it iterates. The * doubly-linked list allows each token to ask its predecessor for the expanded length. */ public final class Phrase
比如:

CharSequence parseStr = Phrase.from("Hi {first_name}, you are {age} years old.")
				 .put("first_name", "UperOne")
				 .put("age", "26")
				 .format();
		
mParseTxt.setText( parseStr );
用起来非常简单。



声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
php怎么将16进制字符串转为数字php怎么将16进制字符串转为数字Oct 26, 2021 pm 06:36 PM

php将16进制字符串转为数字的方法:1、使用hexdec()函数,语法“hexdec(十六进制字符串)”;2、使用base_convert()函数,语法“bindec(十六进制字符串, 16, 10)”。

php怎么将字符串转换成小数php怎么将字符串转换成小数Mar 22, 2023 pm 03:22 PM

PHP 是一门功能强大的编程语言,广泛应用于 Web 开发领域。其中一个非常常见的情况是需要将字符串转换为小数。这在进行数据处理的时候非常有用。在本文中,我们将介绍如何在 PHP 中将字符串转换为小数。

golang怎么检测变量是否为字符串golang怎么检测变量是否为字符串Jan 06, 2023 pm 12:41 PM

检测变量是否为字符串的方法:1、利用​“%T”格式化标识,语法“fmt.Printf("variable count=%v is of type %T \n", count, count)”;2、利用reflect.TypeOf(),语法“reflect.TypeOf(变量)”;3、利用reflect.ValueOf().Kind()检测;4、使用类型断言,可以对类型进行分组。

php怎么将字符串转为布尔类型php怎么将字符串转为布尔类型Jul 01, 2021 pm 06:36 PM

转换方法:1、在转换变量前加上用括号括起来的目标类型“(bool)”或“(boolean)”;2、用boolval()函数,语法“boolval(字符串)”;3、用settype()函数,语法“settype(变量,"boolean")”。

go语言怎么删除字符串中的空格go语言怎么删除字符串中的空格Jan 17, 2023 pm 02:31 PM

删除方法:1、使用TrimSpace()函数去除字符串左右两边的空格,语法“strings.TrimSpace(str)”;2、使用Trim()函数去除字符串左右两边的空格,语法“strings.Trim(str, " ")”;3、使用Replace()函数去除字符串的全部空格,语法“strings.Replace(str, " ", "", -1)”。

php字符串函数学习:怎么去掉前面的字符php字符串函数学习:怎么去掉前面的字符Mar 20, 2023 pm 02:33 PM

在开发PHP应用程序时,有时我们需要去掉字符串前面的某些特定字符或者字符串。在这种情况下,我们需要使用一些PHP函数来实现这一目标。本文将介绍一些PHP函数,帮助您轻松地去掉字符串前面的字符或字符串。

php 字符串长度不一致怎么办php 字符串长度不一致怎么办Feb 07, 2023 am 09:58 AM

php字符串长度不一致的解决办法:1、通过mb_detect_encoding()函数查看字符串的编码方式;2、通过mb_strlen函数查看具体字符长度;3、使用正则表达式“preg_match_all('/[\x{4e00}-\x{9fff}]+/u', $str1, $matches);”剔除非中文字符即可。

php字符串部分乱码怎么办php字符串部分乱码怎么办Jan 20, 2023 am 10:18 AM

php字符串部分乱码的解决办法:1、使用“mb_substr(strip_tags($str),0,-1,'UTF-8');”截取字符串;2、使用“iconv("UTF-8","GB2312//IGNORE",$data)”转换字符集即可。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
2 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。