Android開発の詳細-実戦で発生した詳細な問題と解決策のまとめ


Android開発の詳細-実戦で発生した詳細な問題と解決策のまとめ
これは私の1篇の古い文がMarkDownフォーマットの文章に訳すので、原文の時間は2016-09-05 18:21で、ここはすべてプロジェクトの中で出会う問題をして、資料を調べた後に、結果をみんなに教えます
一、取得システム時間の24時間制と12時間制
最近、プロジェクトをしている間にエラーが発生しました.サーバー側は24時間制で、ローカルデータベースは12時間制です.
1、24時間制の時間を取得する
public static String showDate() {
    SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String date = sDateFormat.format(new Date());
    return date;
}

2、12時間制の時間を取得する
public static String showDate() {
    SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    String date = sDateFormat.format(new Date());
    return date;
}

両者の違いはHHとhhであり,文書の他の例を見ることができる.
二、ViewPagerのFragmentは切り替え時に再ロードしない
最近、プロジェクトをしている間にエラーが発生しました.ViewPagerのFragmentで3ページ目に切り替えて1ページ目に戻すと、1ページ目が再ロードされ、ユーザー体験が低下しているように見えます.viewPagerは現在のページの前後2ページ、つまり3ページ目になると、1ページ目が破棄され、2ページ目に戻ると再作成されるからです.
解決策
//   1
mViewPager.setOffscreenPageLimit(3);  

三、ショッピングカートを最適化し、品物を選択する時、価格を加算して減らす正確な演算
商品のショッピングカートのモジュールを作る時、価格の加減が単純に+、-を使って実現することができないことを発見して、私達の価格はすべてdoubleのタイプのため、例えば10.24元、互いに加減する時20.455555の情況が現れることができて、だから私達はAPIの中でBigDecimalのこの種類を使って包装して、それから演算します
コードは次のとおりです.
public void selectSingle() {
    //  BigDecimal  
    BigDecimal bj1 = new BigDecimal(Double.toString(money1));
    BigDecimal bj2 = new BigDecimal(Double.toString(money2));
    if (selected_Id.contains(shop.get_id())) {//  
        sum_money = bj1.subtract(bj2).doubleValue();
    } else {//  
        sum_money = bj1.add(bj2).doubleValue();
    }
}

効果は以下の通りです:価格はすでに正常なプラスマイナスです
四、アプリケーションはホームキーを押してデスクトップに戻り、再度クリックしてアプリケーションが離れた時のActivityを回復できない
スタックの前のいずれかのActivityがmanifestファイルでsingleTaskとして起動モードを定義している限り、アプリケーションを再度クリックすると最初のActivityが起動し、前のActivityのsingleTaskプロパティを除去すれば離れたときのActivityに戻る
五、放送による傍受ネットワークの変化状況
通常、Wifiが断線してトラフィックがインターネットに接続されるなど、ソフトウェアを使用するときにネットワークが変化する場合があります.この場合、私たちのソフトウェアとしてトラフィックがインターネットに接続されていることをユーザーに通知する必要があります.まず、Manifestsに登録されているネットワークの変化状況のブロードキャスト
<!--    -->
<receiver android:name=".Receiver.NetReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

次に,このReceiverを作成し,ネットワークの変化状況に応じた注意喚起を行う.ここで、ユーザがWifiをオンまたはオフにすると、ブロードキャストは受信することができる
public class NetReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //       
        if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeInfo = connectivityManager.getActiveNetworkInfo();
            NetworkInfo netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            NetworkInfo wifiInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            if (activeInfo != null) {
                //    
                if (activeInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                    //      
                    if (netInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                        Toast.makeText(context, "         ", Toast.LENGTH_SHORT).show();
                    }
                    //  Wifi  
                    if (wifiInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                        Toast.makeText(context, "     Wifi  ", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(context, "          ", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}

六、Gradleを最適化し、コンパイル時間を33.8秒から4.5秒に下げる
プロジェクトのgradleに次の文を追加します.
 tasks.whenTaskAdded { task ->
    if (task.name.contains("lint")
            || task.name.equals("clean")
            || task.name.contains("Aidl")
            || task.name.contains("mockableAndroidJar")
            || task.name.contains("UnitTest")
            || task.name.contains("AndroidTest")
            || task.name.contains("Ndk")
            || task.name.contains("Jni")
    ) {
        task.enabled = false;
    }
}

七、Fragmentの怠け者ロードベース
プロジェクトにベースクラスを追加すると、新しいFragmentがBaseFragmentを継承することで、Fragmentの怠惰なロードを簡単に実現できます.
public abstract class BaseFragment extends Fragment implements View.OnClickListener {

    private boolean isPrepared;
    private boolean isVisible;

    public abstract View initViews(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);

    public abstract void initData();

    public abstract void initListener();

    public abstract void processClick(View v);

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (getUserVisibleHint()) {
            isVisible = true;
            lazyLoad();
        } else {
            isVisible = false;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return initViews(inflater, container, savedInstanceState);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        isPrepared = true;
        lazyLoad();
    }

    /** *     */
    private void lazyLoad() {
        if (!isVisible || !isPrepared) {
            return;
        }
        //    
        initData();
        initListener();
    }


    @Override
    public void onClick(View v) {
        processClick(v);
    }
}

八、最適化エラー、エラーによるプログラムのクラッシュを防止
プロジェクトではlist.get(0)データがないとプログラムがクラッシュします.このときはプログラムtry-catchを起こして、プログラムが間違っているがクラッシュしないようにしなければなりません.例えば
public Drawable getDrawable(String name) {
    try {
        return mResources.getDrawable(mResources.getIdentifier(name, "drawable", mPkgName));
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

九、Contextの応用シーン
十、PhotoViewがViewPagerでマルチタッチした場合、クラッシュを誤報する方法を解決する
PhotoViewを使用してViewPagerでマルチマップ操作を示します.操作が頻繁すぎる場合は、次のエラーが発生します.
java.lang.IllegalArgumentException: pointerIndex out of range  

その解決策としてPhotoViewが存在するActivityに次のような処理を追加すればよい.
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    try {
        return super.dispatchTouchEvent(ev);
    } catch (IllegalArgumentException ex) {
        ex.printStackTrace();
    }
    return false;
}

十一、Htmlを使用する.fromhtml表示画像
プロジェクト開発では、バックグラウンドでこのようなエディタを使用して図を編集することがよくあります.
返されるandroid端はhtml文字列で、このときはHtmlだけです.fromhtmlは画像を表示できません.画像は小さな四角形に置き換えられます.次は私が処理したクラスです.このクラスはHtmlだけです.fromhtmlは画像を認識するとクラスのgetDrawable()メソッドをコールバックする.このクラスはネットワークピクチャとサーバピクチャに互換性があり、以下の2つのフォーマットに互換性があります.
サーバ画像url:/upload/2017/05/04/590 aae 1 b 0 d 4 a.pngネットワーク画像url:https://p.ssl.qhimg.com/t0140ba2595bb1b8c4a.png
/** * @author     2017/6/7 */
public class ImageGetterImpl implements Html.ImageGetter {

    private int width, height;
    private TextView tv;
    private String html;
    private File file;

    public ImageGetterImpl(TextView tv, String html, int width, int height) {
        this.tv = tv;
        this.html = html;
        this.width = width - 80;
        this.height = height;
    }

    @Override
    public Drawable getDrawable(String source) {
        Drawable drawable = null;
        //               ,        ,      
        if (!source.startsWith("http")) {
            source = RequestCenter.ROOT_URL + source;
        }
        //            
        String[] fileName = source.split("/");
        file = new File(Environment.getExternalStorageDirectory(), fileName[fileName.length - 1]);
        //      http  
        if (source.startsWith("http")) {
            //         
            if (file.exists()) {
                //      drawable
                drawable = Drawable.createFromPath(file.getAbsolutePath());
                //                 
                height = (width) * drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth();
                drawable.setBounds(0, 0, width, height);
            } else {
                //                 
                AsyncLoadNetworkPic networkPic = new AsyncLoadNetworkPic();
                networkPic.execute(source);
            }
        }
        return drawable;
    }

    public class AsyncLoadNetworkPic extends AsyncTask<String, Integer, Void> {
        @Override
        protected Void doInBackground(String... params) {
            //       
            loadNetPic(params);
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            //               
            tv.setText(Html.fromHtml(html, new ImageGetterImpl(tv, html, width, height), null));
        }
        /** *        */
        private void loadNetPic(String... params) {
            String path = params[0];
            InputStream in = null;
            FileOutputStream out = null;
            try {
                URL url = new URL(path);
                HttpURLConnection connUrl = (HttpURLConnection) url.openConnection();
                connUrl.setConnectTimeout(10000);
                connUrl.setRequestMethod("GET");
                if (connUrl.getResponseCode() == 200) {
                    in = connUrl.getInputStream();
                    out = new FileOutputStream(file);
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                } else {
                    Log.e("TAG", connUrl.getResponseCode() + "");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

対応するアンドロイド端では3つのパラメータの方法を用いてhtml文字列を解析し,ここでDensityUtilsの2つの方法は取得画面の幅と高さを表す
tv_content.setText(Html.fromHtml(data.getContent(),
                new ImageGetterImpl(tv_content, data.getContent(),
                        DensityUtils.getDisplayWidth(this),
                        DensityUtils.getDisplayHeight(this)), null));

携帯電話での表示効果は以下の通りです.