目录
Android字符串格式化开源库phrase介绍
首页 后端开发 php教程 Android字符串格式化开源库phrase介绍_PHP教程

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

Jul 13, 2016 am 10:18 AM
字符串

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 <= 'z') { return key(prev); } else { throw new IllegalArgumentException( "Unexpected character '" + nextChar + "'; expected key."); } } return text(prev); } /** Parses a key: "{some_key}". */ private KeyToken key(Token prev) { // Store keys as normal Strings; we don't want keys to contain spans. StringBuilder sb = new StringBuilder(); // Consume the opening '{'. consume(); while ((curChar >= 'a' && curChar <= 'z') || curChar == '_') { sb.append(curChar); consume(); } // Consume the closing '}'. if (curChar != '}') { throw new IllegalArgumentException("Missing closing brace: }"); } consume(); // Disallow empty keys: {}. if (sb.length() == 0) { throw new IllegalArgumentException("Empty key: {}"); } String key = sb.toString(); keys.add(key); return new KeyToken(prev, key); } /** Consumes and returns a token for a sequence of text. */ private TextToken text(Token prev) { int startIndex = curCharIndex; while (curChar != '{' && curChar != EOF) { consume(); } return new TextToken(prev, curCharIndex - startIndex); } /** Consumes and returns a token representing two consecutive curly brackets. */ private LeftCurlyBracketToken leftCurlyBracket(Token prev) { consume(); consume(); return new LeftCurlyBracketToken(prev); } /** Returns the next character in the input pattern without advancing. */ private char lookahead() { return curCharIndex < pattern.length() - 1 ? pattern.charAt(curCharIndex + 1) : EOF; } /** * Advances the current character position without any error checking. Consuming beyond the * end of the string can only happen if this parser contains a bug. */ private void consume() { curCharIndex++; curChar = (curCharIndex == pattern.length()) ? EOF : pattern.charAt(curCharIndex); } private abstract static class Token { private final Token prev; private Token next; protected Token(Token prev) { this.prev = prev; if (prev != null) prev.next = this; } /** Replace text in {@code target} with this token's associated value. */ abstract void expand(SpannableStringBuilder target, Map 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 );
登录后复制
用起来非常简单。



www.bkjia.comtruehttp://www.bkjia.com/PHPjc/885681.htmlTechArticleAndroid字符串格式化开源库phrase介绍 在上一篇博客Android通过String.format式化(动态改变)字符串资源的显示内容中介绍了通过String.format来式...
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热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 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

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

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP中int类型转字符串的方法详解 PHP中int类型转字符串的方法详解 Mar 26, 2024 am 11:45 AM

PHP中int类型转字符串的方法详解在PHP开发中,经常会遇到将int类型转换为字符串类型的需求。这种转换可以通过多种方式实现,本文将详细介绍几种常用的方法,并附带具体的代码示例来帮助读者更好地理解。一、使用PHP内置函数strval()PHP提供了一个内置函数strval(),可以将不同类型的变量转换为字符串类型。当我们需要将int类型转换为字符串类型时,

Golang中如何检查字符串是否以特定字符开头? Golang中如何检查字符串是否以特定字符开头? Mar 12, 2024 pm 09:42 PM

Golang中如何检查字符串是否以特定字符开头?在使用Golang编程时,经常会遇到需要检查一个字符串是否以特定字符开头的情况。针对这一需求,我们可以使用Golang中的strings包提供的函数来实现。接下来将详细介绍如何使用Golang检查字符串是否以特定字符开头,并附上具体的代码示例。在Golang中,我们可以使用strings包中的HasPrefix

Golang字符串是否以指定字符结尾的判断方法 Golang字符串是否以指定字符结尾的判断方法 Mar 12, 2024 pm 04:48 PM

标题:Golang中判断字符串是否以指定字符结尾的方法在Go语言中,有时候我们需要判断一个字符串是否以特定的字符结尾,这在处理字符串时十分常见。本文将介绍如何使用Go语言来实现这一功能,同时提供代码示例供大家参考。首先,让我们来看一下Golang中如何判断一个字符串是否以指定字符结尾的方法。Golang中的字符串可以通过索引来获取其中的字符,而字符串的长度可

python怎么重复字符串_python重复字符串教程 python怎么重复字符串_python重复字符串教程 Apr 02, 2024 pm 03:58 PM

1、首先打开pycharm,进入到pycharm主页。2、然后新建python脚本,右键--点击new--点击pythonfile。3、输入一段字符串,代码:s="-"。4、接着需要把字符串里面的符号重复20次,代码:s1=s*20。5、输入打印输出代码,代码:print(s1)。6、最后运行脚本,在最底部会看到我们的返回值:-就重复了20次。

解决PHP中16进制转字符串出现中文乱码的方法 解决PHP中16进制转字符串出现中文乱码的方法 Mar 04, 2024 am 09:36 AM

解决PHP中16进制转字符串出现中文乱码的方法在PHP编程中,有时候我们会遇到需要将16进制表示的字符串转换为正常的中文字符的情况。然而,在进行这个转换的过程中,有时会遇到中文乱码的问题。这篇文章将为您提供解决PHP中16进制转字符串出现中文乱码的方法,并给出具体的代码示例。使用hex2bin()函数进行16进制转换PHP内置的hex2bin()函数可以将1

PHP字符串匹配技巧:避免模糊包含表达式 PHP字符串匹配技巧:避免模糊包含表达式 Feb 29, 2024 am 08:06 AM

PHP字符串匹配技巧:避免模糊包含表达式在PHP开发中,字符串匹配是一个常见的任务,通常用于查找特定的文本内容或验证输入的格式。然而,有时候我们需要避免使用模糊的包含表达式来确保匹配的准确性。本文将介绍一些在PHP中进行字符串匹配时避免模糊包含表达式的技巧,并提供具体的代码示例。使用preg_match()函数进行精确匹配在PHP中,可以使用preg_mat

PHP字符串操作:有效去除空格的实用方法 PHP字符串操作:有效去除空格的实用方法 Mar 24, 2024 am 11:45 AM

PHP字符串操作:有效去除空格的实用方法在PHP开发中,经常会遇到需要对字符串进行去除空格操作的情况。去除空格可以使得字符串更加整洁,方便后续的数据处理和显示。本文将介绍几种有效的去除空格的实用方法,并附上具体的代码示例。方法一:使用PHP内置函数trim()PHP内置函数trim()可以去除字符串两端的空格(包括空格、制表符、换行符等),非常方便且简单易用

PHP实现删除字符串最后两个字符的技巧 PHP实现删除字符串最后两个字符的技巧 Mar 23, 2024 pm 12:18 PM

PHP作为一种广泛应用于开发Web应用程序的脚本语言,其字符串处理功能十分强大。在日常开发中,经常会遇到需要删除字符串的操作,特别是删除字符串的最后两个字符。本文将介绍两种PHP实现删除字符串最后两个字符的技巧,并提供具体的代码示例。技巧一:使用substr函数PHP中的substr函数用于返回字符串的一部分。通过指定字符串和起始位置,我们可以轻松地删除字符

See all articles