android一些问题解决

来源:互联网 发布:剑网3天策数据 编辑:程序博客网 时间:2024/05/01 15:28

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">1.启动APP时闪退,日志错误显示为 </span>

<span style="font-size:14px;">java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setOnClickListener(android.view.View$OnClickListener)' on a null object reference</span>
最终在StackOverFlow中找到原因及解决办法,原因是我在主Activity中设置点击事件的这个ImageButton是在我的ListView的单独的Item布局文件中,即ListView和Item是两个Layout的xml,而主Activity中  setContentView(R.layout.activity_phone_list);  是设置ListView所在的布局文件为Activity的显示界面,所以其实主Activity是获取不到Item布局文件中定义的那个ImageButton的引用的,自然当设置监听事件时会报null object reference。

下图为StackOverFlow 中的回答,箭头部分表示要从接收该布局文件的Activity中获得该组件。


还有另一位博主的一篇文章讲为ListView每个Item上面的按钮添加事件,地址为 为ListView每个Item上面的按钮添加事件,其中的第二种方法值得借鉴。




2.ListView的Item无法响应点击事件(不能获得焦点can't take focus),因为我在Item布局文件中加入了一个ImageButton,而它默认会主动获得焦点


 “ 通常,我们会自定义 ListView Item 的 Layout,当自定义的 Item Layout 含有主动获得焦点的控件时(例如 Button, ImageButton 等),那么我们就没办法点击 ListView Item 自己的点击事件。

解决办法很简单,只要在Item Layout 的根布局中加上 android:descendantFocusability = "blocksDescendants"属性即可。如下方的 Item 布局文件所示:

Java

这里再说说 descendantFocusability 这个属性的作用。

根据 官方说明 ,descendantFocusability 定义了 ViewGroup 和子控件的在获取焦点时的关系。

有下面三种取值:

  • beforeDescendants,ViewGroup 会在所有子控件之前获得焦点
  • afterDescendants,ViewGroup 会在所有子控件都不需要焦点时获得焦点
  • blocksDescendants,ViewGroup会阻断子控件获得焦点。

通常,我们只要把 descendantFocusability 设置为 blocksDescendants,即可解决由于 Item 里的 Button 抢夺焦点导致 Item 本身无法点击的问题。”

以上是网搜到的Item抢占焦点的办法,,然而这样我Item中的ImageButton也不能点击了,我想的是每个item一个点击事件,Item中的ImageButton(Button也适用)有自己单独的点击事件,实现不同的功能,而不是只能点击整个Item一个事件,还没解决,未完待续……

接上面的问题,我看到别人关于item和item中点击事件都生效的一篇文章在Activity中响应ListView内部按钮的点击事件,其中介绍了使用接口回调使用抽象类回调两种方法,我试了一下抽象类回调然后加上之前的descendantFocusability 设置为 blocksDescendants,成功解决了Item和Item中控件不同的点击响应。


3.如何变相地改变启动页以避免用户每次启动APP时都要登录,有一种解决办法是将用户名密码保存在SharedPreferences里面,然后将加载界面设置为启动页,在加载的时候验证SharedPreferences中用户名密码是否存在并且正确,如果正确则在加载后启动登录后的界面,不是则加载后进入登录界面。


4.loading(加载)页中用线程做一个ImageView的Alpha渐变动画效果然后设置一段时间延迟启动其他界面,如

 launch.postDelayed(new Runlaunch(),2500);//设置2.5秒钟延迟执行Runlaunch线程,launch是新建的Handler对象
我直接贴自己的代码吧

    private ImageView ivstart1,ivstart2;    static int image_alpha1=255;//第一段动画Alpha值    static int image_alpha2=0;//第二段动画Alpha值    Handler launch;    boolean isrun1=true;//线程是否执行第一段动画    boolean isrun2=false;//线程是否执行第二段动画    private int runtime=0;//用以判断该轮到哪段动画了,变量递增,递增到100时换第二段动画    static boolean isLogin=false;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_launch);        init();        ivstart2.setAlpha(image_alpha2);        new Thread(new Runnable() {            @Override            public void run() {                while(isrun1){                    try {                        Thread.sleep(70);//每次线程睡眠时间70ms                        updateAlpha();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                while(isrun2){                    try {                        Thread.sleep(100);                        updateAlpha();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();        //接收消息之后更新imageview视图        launch=new Handler(){            public void handleMessage(Message msg){                super.handleMessage(msg);                ivstart1.setAlpha(image_alpha1);                ivstart2.setAlpha(image_alpha2);                ivstart1.invalidate();//刷新视图                ivstart2.invalidate();            }        };        launch.postDelayed(new Runlaunch(),2500);//设置2.5秒钟延迟执行Runlaunch线程    }    private void updateAlpha() {        while(runtime<100){            if (image_alpha1 > 120) {                image_alpha1-=14;            }else{                image_alpha1=0;                isrun1=false;                image_alpha2=100;            }            runtime+=10;            break;        }        while(runtime>=100){            isrun2=true;            if(image_alpha2<200){                image_alpha2+=10;            }else{                image_alpha2=255;                isrun2=false;            }            runtime+=10;            break;        }        launch.sendMessage(launch.obtainMessage()); // 发送需要更新imageview视图的消息-->这里是发给主线程    }    class Runlaunch implements Runnable{        @Override        public void run() {            startActivity(new Intent(LaunchActivity.this,LoginActivity.class));            LaunchActivity.this.finish();        }    }
我这里是设置了两段渐变动画,就用自己定义的一个runtime变量区分,runtime为0~100时第一段Alpha动画,递增到100时换成第二段Alpha动画。过程是这样的,线程每次先判断布尔值isrun是否为真,是则执行改变Alpha的方法updateAlpha(),方法中每次改变Alpha值时,都要发送需要更新ImageView视图的消息给Handler对象launch,然后launch设置Alpha值并且刷新视图,这样通过每次短时间间隔的刷新ImageView的Alpha值看上去就好像是一个持续的渐变动画了。

5.Android获取系统当前时间

一:

import    java.text.SimpleDateFormat;              SimpleDateFormat    formatter    =   new    SimpleDateFormat    ("yyyy年MM月dd日    HH:mm:ss     ");  //这部分格式可以自己改,比如<pre name="code" class="java" style="font-size: 14px; line-height: 25.2px;">"yyyy-MM-dd    HH时mm分" 这样,在其中插入换行符这些也可以
Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate);

二:用android中的Time类

import android.text.format.Time;           Time t=new Time();            t.setToNow();//取得系统时间            String year=t.year+"年"+t.month+"月"+t.monthDay+"日"+"  "+t.hour+":"+t.minute+":"+t.second;

如何获取系统时间是12小时制还是24小时制?

ContentResolver cv = getContentResolver();         String strTimeFormat =android.provider.Settings.System.getString(cv,                                            android.provider.Settings.System.TIME_12_24); //android是小写!                 if(strTimeFormat.equals("24"))        {                Log.i("timeformat","24");         }else Log.i("timeformat","12"); 


6.报错

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare();
原因及解决办法:

Android basically works on two thread types namely UI thread and background thread. According to android documentation -

Do not access the Android UI toolkit from outside the UI thread to fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:

Activity.runOnUiThread(Runnable)  View.post(Runnable)  View.postDelayed(Runnable, long)

Now there are various methods to solve this problem. I will explain it by code sample

runOnUiThread

new Thread(){    public void run()    {        myactivity.this.runOnUiThread(new runnable()        {            public void run()            {                //Do your UI operations like dialog opening or Toast here            }        });    }}.start();

LOOPER

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

class LooperThread extends Thread {    public Handler mHandler;    public void run() {        Looper.prepare();        mHandler = new Handler() {            public void handleMessage(Message msg) {                // process incoming messages here            }        };        Looper.loop();    }

AsyncTask

AsyncTask allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.

public void onClick(View v) {    new CustomTask().execute((Void[])null);}private class CustomTask extends AsyncTask<Void, Void, Void> {    protected Void doInBackground(Void... param) {        //Do some work        return null;    }    protected void onPostExecute(Void param) {        //Print Toast or open dialog    }}

Handler

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.

Message msg = new Message();    new Thread()    {        public void run()        {            msg.arg1=1;            handler.sendMessage(msg);        }    }.start();    Handler handler = new Handler(new Handler.Callback() {        @Override        public boolean handleMessage(Message msg) {            if(msg.arg1==1)            {                //Print Toast or open dialog                    }            return false;        }    });

7.报错

android.content.res.Resources android.content.Context.getResources()' on a null object reference
解决办法:为在出错的地方为context处加上上下文,可以是onCreate方法里面构造的时候添加MainActivity.this等Context内容

 Bitmap bitmap=downloadImage();            BitmapDrawable bd=new BitmapDrawable(context.getResources(),bitmap);//Create drawable from a bitmap, setting initial target density based on

8.LinearLayout分开布局

我们知道LinearLayout是按照指定的朝向(orientation)顺序地摆放组件的,所以有一种推荐的分开布局方法是在其中加入一个看不见的View,如水平布局中想要左右分开布局,使控件分别在左右两端可以这样

        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orietation="horizontal">            <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="start"                android:text="zzz"/>            <!--加入“隐形”View达到LinearLayout左右布局的目的-->            <View                android:layout_width="0dp"                android:layout_weight="1.0"                android:layout_height="0dp"/>            <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:gravity="right"                android:text="yyy" />        </LinearLayout>

看不见的View填充了中间的空白部分。









0 0