0

この問題は私に私の正気を疑わせています。私はAndroidのバグに遭遇したと思いますが、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

そして、 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

この問題は、エミュレーターと、2.2から4.1までの異なるOSを実行している3つの異なる電話で発生しています。

では、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());
        }
    }

}

更新-これは間違いなくNumberFormat.getIntegerInstance()の問題です

Integer.toString(balance); 何の問題もありません。では、どうすれば整数をコンマで確実にフォーマットできますか?

4

1 に答える 1

1

私はアンドロイドにバグがあるとかなり確信しています。NumberFormat.getIntegerInstance()http://developer.android.com/reference/java/text/NumberFormat.html )のドキュメントを見ると、このメソッドは何度も呼び出されるべきではないという言及があります。整数インスタンスを1回、メンバー変数として設定して再利用します。引用

複数の数値をフォーマットする場合は、フォーマットを取得して複数回使用する方が効率的であるため、システムは現地の言語や国の規則に関する情報を複数回フェッチする必要がありません。

もちろんそうですが、このようなパフォーマンスの問題は他のクラスでは実際には言及されていないため、Androidチームは、このメソッドが頻繁に呼び出されると少し信頼性が低くなる可能性があることを認識していると思いますが、実際には何もしませんそれについて。もしそうなら、なぜ彼らがすべきなのか、私はおそらく同意するでしょう。コードを最適化するのは開発者の責任であり、コードが最適化されていれば問題は発生しません。

問題は、私のコードがまったく最適化されていないということです。この方法は、すべて同時にロードされている複数のスピナーで使用されていたためです。

コードをリファクタリングし、結果をメンバー変数に割り当て、メンバー変数がnullですべてが良好と思われる場合にのみ呼び出すことで、このメソッドができるだけ少なく呼び出されるようにしましたが、機能はそれができるほど安定しておらず、これが再び噛み付く可能性があります。

于 2013-03-02T12:15:37.273 に答える