Android NumberFormat.getIntegerInstance()。格式不可靠。如何格式化整数? Android漏洞?

时间:2013-02-05 19:34:46

标签: android textview

这个问题让我怀疑自己的理智。我想我已经遇到了一个android bug,我需要解决NumberFormat.getIntegerInstance()。format的替代解决方案。

我在格式化数字显示在TextView中时遇到问题 这是一个间歇性的问题,但不可靠地重现。

我有一个方法,每次通过片段中的回调事件选择微调器项目时计算余额。有6个微调器,选择哪个是无关紧要的

有时可能需要30或40次点击(微调器上的选择)才能显示问题,有时只需要10或12次点击。该问题与实际值完全无关,calcBalance方法始终返回格式化的整数。只是有时整数在TextView中显示为空白文本。

问题是setText方法正在运行它只是不显示的数字。

一旦问题出现,几乎每次选择都会发生。在横向和纵向之间切换似乎可以解决问题,但它会重新开始

calcBalance方法看起来像这样

public String calcBalance() {
    int balance = 90000000;
    for(int i = 0; i < this.cars.size(); i++){
        balance = balance - this.cars.get(i).getDriver().getPrice();
        balance = balance - this.cars.get(i).getChassis().getPrice();
        balance = balance - this.cars.get(i).getEngine().getPrice();
        Log.i("@@@@", "Calculating balance: " + balance);
    }
    return NumberFormat.getIntegerInstance().format(balance);
}

使用调试消息调用此平衡的方法如下所示

    @Override
    public void onBalanceChanged(int position, CarModel car) {
//      Try to change the car but if it has not already been added then add it instead using outOfBounds
//      exception to check if item exists
        mi ++;
        try {
            mTeam.cars.set(position, car);
        }catch(java.lang.IndexOutOfBoundsException e){
            mTeam.cars.add(car);
        }
        if (mTvBalance == null){
            mTvBalance = (TextView) findViewById(R.id.lblBalance);
        }
        String balance = mTeam.calcBalance();
        Util.log_debug_message("Setting text Balance is " + balance);
        String balance_text = mi + " Available Balance: $" + balance;  
        Util.log_debug_message("Balance text is " + balance_text);
        mTvBalance.setText(balance_text);
    }

示例日志输出表明我正在设置的文本的值是

  

余额文本为25可用余额:$ 10,000,000

然而,文本视图仅显示

  

25可用余额:

25号只是我调试的一部分,用于证明TextView.setText实际上已经设置好,而且只是未显示的数字。

导致TextView只显示没有值的文本的日志输出(包括上面的示例如下

W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4514fe58
I/@@@@    ( 1249): Calculating balance: 45000000
I/@@@@    ( 1249): Calculating balance: 0
D/QuizApp ( 1249): Setting text Balance is 0
D/QuizApp ( 1249): Balance text is 24 Available Balance: $0
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@450f3ec0
I/@@@@    ( 1249): Calculating balance: 45000000
I/@@@@    ( 1249): Calculating balance: 10000000
D/QuizApp ( 1249): Setting text Balance is 10,000,000
D/QuizApp ( 1249): Balance text is 25 Available Balance: $10,000,000
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4517e3d0
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@451c4b70
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4513fef8
I/@@@@    ( 1249): Calculating balance: 45000000
I/@@@@    ( 1249): Calculating balance: 13000000
D/QuizApp ( 1249): Setting text Balance is 13,000,000
D/QuizApp ( 1249): Balance text is 26 Available Balance: $13,000,000
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@45115e48

DO 在TextView中设置正确文本的时间的一些日志输出

I/@@@@    ( 1249): Calculating balance: 45000000
I/@@@@    ( 1249): Calculating balance: 0
D/QuizApp ( 1249): Setting text Balance is 0
D/QuizApp ( 1249): Balance text is 8 Available Balance: $0
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@45020d10
I/@@@@    ( 1249): Calculating balance: 55000000
I/@@@@    ( 1249): Calculating balance: 10000000
D/QuizApp ( 1249): Setting text Balance is 10,000,000
D/QuizApp ( 1249): Balance text is 9 Available Balance: $10,000,000
W/InputManagerService(   59): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@44f85c58
I/@@@@    ( 1249): Calculating balance: 55000000
I/@@@@    ( 1249): Calculating balance: 20000000
D/QuizApp ( 1249): Setting text Balance is 20,000,000
D/QuizApp ( 1249): Balance text is 10 Available Balance: $20,000,000

我只能假设我收到一些不可打印的字符,有时会从调用NumberFormat.getIntegerInstance().format

返回

我在模拟器和3个不同的手机上遇到这个问题,运行不同的操作系统从2.2到4.1。

那么我有什么其他选择来格式化数字,因为它可以在TextView中可靠地显示?

更新完整片段活动

public class NewTeamFragmentActivity extends SherlockFragmentActivity implements TabListener, OnBalanceChangedListener, OnTeamDataChangedListener{

    static final int NUM_ITEMS = 3;
    private ViewPager mPager;
    private NewTeamSwipeAdapter mAdapter;
    private TeamModel mTeam;
    private TextView mTvBalance;
    private int mi = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_team);
        // Show the Up button in the action bar.
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setNavigationMode( ActionBar.NAVIGATION_MODE_TABS );
        mAdapter = new NewTeamSwipeAdapter(getSupportFragmentManager());

        mPager = (ViewPager)findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);
        mPager.setOnPageChangeListener(
                new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        // When swiping between pages, select the
                        // corresponding tab.
                        getSupportActionBar().setSelectedNavigationItem(position);
                    }
                });
        setupTabs();
        setupModels();
        createFragments();
    }

    private void createFragments() {
        NewTeamFragment teamFragment = new NewTeamFragment();
        Bundle arguments = new Bundle();
        FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
        trans.replace(R.id.new_team_fragment_container, teamFragment);
        trans.commit();
    }

    private void setupModels() {
        mTeam = new TeamModel();
    }

    private void setupTabs() {
        add_tab("Car 1");
        add_tab("Car 2");
        add_tab("Submit Team");
    }

    private void add_tab(String tabText) {
        Tab tab = getSupportActionBar().newTab();
        tab.setText(tabText);
        tab.setTabListener(this);
        getSupportActionBar().addTab(tab);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getSupportMenuInflater().inflate(R.menu.activity_new_team, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            // This ID represents the Home or Up button. In the case of this
            // activity, the Up button is shown. Use NavUtils to allow users
            // to navigate up one level in the application structure. For
            // more details, see the Navigation pattern on Android Design:
            //
            // http://developer.android.com/design/patterns/navigation.html#up-vs-back
            //
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    public static class NewTeamSwipeAdapter extends FragmentPagerAdapter {

        public NewTeamSwipeAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        @Override
        public Fragment getItem(int position) {
            Fragment return_frag = null;
            if (position < 2){
                Bundle arguments = new Bundle();
                arguments.putInt(KeyConstants.CAR_ID_KEY, position);
                NewCarFragment fragment = new NewCarFragment();
                fragment.setArguments(arguments);
                return_frag = fragment;
            } else if (position == 2) {
                SubmitTeamFragment fragment = new SubmitTeamFragment();
                return_frag = fragment;
            }
            return return_frag;
        }

        @Override
        public CharSequence getPageTitle (int position){
            CharSequence title = "Unknown!";
            if (position < 2){
                title = "Car " + (position + 1);
            }else if(position == 2){
                title = "Submit Team";
            }
            return title;
        }
    }
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onBalanceChanged(int position, CarModel car) {
//      Try to change the car but if it has not already been added then add it instead using outOfBounds
//      exception to check if item exists
        mi ++;
        try {
            mTeam.cars.set(position, car);
        }catch(java.lang.IndexOutOfBoundsException e){
            mTeam.cars.add(car);
        }
        if (mTvBalance == null){
            mTvBalance = (TextView) findViewById(R.id.lblBalance);
        }
        String balance = mTeam.calcBalance();
        Util.log_debug_message("Setting text Balance is " + balance);
        String balance_text = mi + " Available Balance: $" + balance;  
        Util.log_debug_message("Balance text is " + balance_text);
        mTvBalance.setText(balance_text);
    }

    @Override
    public void onTeamDataChanged(TeamModel mTeam) {
        // TODO Auto-generated method stub
        if (this.mTeam == null){
            this.mTeam = mTeam;
        }else{
            this.mTeam.setTeamName(mTeam.getTeamName());
        }
    }

}

UPDATE - 这绝对是NumberFormat.getIntegerInstance()的问题

Integer.toString(平衡);没有任何问题。那么如何用逗号可靠地格式化整数呢?

1 个答案:

答案 0 :(得分:1)

我很确定android中有一个bug。 查看NumberFormat.getIntegerInstance()http://developer.android.com/reference/java/text/NumberFormat.html)的文档,提到这个方法不应该被调用太多次,因为它更好地获得整数实例一次性能,将其设置为成员变量并重新使用它。 报价

  

如果要格式化多个数字,则获取效率会更高   格式并多次使用它,以便系统没有   获取有关本地语言和国家/地区的信息   约定多次。

当然这是因为这样的性能问题在其他类中并没有真正提到,所以我怀疑Android团队意识到如果过于频繁地调用这个方法可能会有点不可靠,但他们并没有真正去做任何事情。我可能会同意,如果是这样的话那他们为什么要这样呢?由开发人员来优化代码,如果代码经过优化,那么你就不会遇到问题。

问题是我的代码根本没有优化。因为这个方法被用于多个同时加载的微调器。

我已经重构了我的代码并确保通过将结果分配给成员变量来尽可能少地调用此方法,并且只有在成员变量为null并且一切看起来都很好但我感到不安时才调用它感觉功能不是那么稳定,而且可能会回来咬人。