初始化数组如何变为null?

时间:2014-04-19 16:09:35

标签: android nullpointerexception android-activity

以下是代码:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    overridePendingTransition(R.anim.fadein, R.anim.fadeout);
    setContentView(R.layout.startpage);

    rowItems = new ArrayList<RowItem>();

    //... Filling this array.
}

稍后,来自另一个活动StartPage.rowItems.size()抛出NullPointerException

它可能是0(无法检索数据或我做.clear()),但是怎么样,它变成了空?我绝对不会把它设置为null。 还有一点 - 这个数组变量是公共静态的,我从另一个活动中使用它。是否有可能android卸载父活动(包含整个应用程序的所有全局变量)?

P.S。我无法更彻底地检查它,因为我的模拟器/设备中没有出现此错误,但我在Google Play上报告了此错误。所以我无法检查之前和数组变为空时的内容......

谢谢

更准确的代码:

public class StartPage extends Activity implements View.OnTouchListener {

public static List<RowItem> rowItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    overridePendingTransition(R.anim.fadein, R.anim.fadeout);
    setContentView(R.layout.startpage);
    rowItems = new ArrayList<RowItem>();
    pDialog = new ProgressDialog(this);
    pDialog.setMessage("Loading data...");
    pDialog.setCancelable(false);
    pDialog.show();
    gc=new GetData();gc.execute();
}

public class GetData extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        rowItems.clear();
        inProgress=true;
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        ServiceHandler sh = new ServiceHandler();
        String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
        if (jsonStr != null) {
            try {
                JSONObject jsonObj = new JSONObject(jsonStr);
                items = jsonObj.getJSONArray(TAG_COINS);
                for (int i = 0; i < itemss.length(); i++) {
                    JSONObject c = items.getJSONObject(i);

                    String id = c.getString(TAG_ID).toUpperCase();
                    String price = c.getString(TAG_PRICE);
                    String name = c.getString(TAG_NAME);
                    RowItem item = new RowItem(id, name, price);
                    rowItems.add(item);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else {
            Log.e("ServiceHandler", "Couldn't get any data from the url");
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        inProgress=false;
        pDialog.dismiss();
    }
}

然后调用另一个活动:

public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_UP:
        int x = (int) event.getX();
        int y = (int) event.getY();
        int w=view.getWidth()-20;
        int h=view.getHeight()-20;
        if (x<w*0.05 || x>w*0.95 || y<h*0.13 ) return false; // Misclicked

        if (x<w*0.5 && y<h*0.38) {             
            Intent intent = new Intent(this, MainActivity.class);
            startActivity(intent);
        }
}
    return true;
} 

在另一个活动(MainActivity)上,尝试使用主要活动中的数据刷新列表视图:

public class MainActivity extends ListActivity implements View.OnClickListener {
void refresh_list() {
    if (StartPage.rowItems.size()>0) {  <-- Here is NPE
    ListAdapter adapter = new CustomListAdapter(MainActivity.this,R.layout.list_item,StartPage.rowItems); 
    setListAdapter(adapter);
    ((BaseAdapter) getListAdapter()).notifyDataSetChanged();
    }
}

Google Play报道:

Caused by: java.lang.NullPointerException
at halfprice.coinmanager.MainActivity.refresh_list(MainActivity.java:116)
at halfprice.coinmanager.MainActivity.onCreate(MainActivity.java:105)
at android.app.Activity.performCreate(Activity.java)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java)

希望这会有所帮助......

3 个答案:

答案 0 :(得分:0)

如果我没弄错的话: 启动活动后,将调用onCreate()方法。 但是当你从另一个活动回到同一个活动时,会跳过onCreate方法并调用onResume()方法。所以我的建议是在onResume()方法中进行初始化

@Override
protected void onResume(Bundle savedInstanceState) {
    overridePendingTransition(R.anim.fadein, R.anim.fadeout);
    setContentView(R.layout.startpage);

    rowItems = new ArrayList<RowItem>();

    //... Filling this array.
}

答案 1 :(得分:0)

您正在静态ArrayList中加载数据并将其接收到不同的活动。这不是一个好习惯。

让我先说出你在Oncreate()中创建了这个对象的答案。你做得更好,全球创造它不会发生这个问题。

示例:

public class StartPage extends Activity implements View.OnTouchListener {

public static List<RowItem> rowItems = new ArrayList<RowItem>(); 

OnCreate(){
   //and perform the action you want to do.  

}
//Hope this will help you definately.

现在另一种方法是编程语言的优秀实践

将数据对象从一个Activity传递到另一个Activity很简单,如果要传递Array对象,则应该序列化对象。例如;

ArrayList rowItems = new ArrayList();

对于传递数组对象,你必须使用intent PutExtra,例如:

Intent intent = new Intent(SplashScreen.this, MainActivity.class);

intent.putExtra("key",array); startActivity(intent);

//intent.putExtra("key",array); will show error if your Model class is not  implements Serializable  eg: public class Model  implements Serializable{

String id;
String price;
String name;
//generate your getter setter and set data in to this.
}

//For getting data in to another class just use

ArrayList<Model> data = (ArrayList<Model>)getIntent().getSerializable("key");

现在你可以使用这个数据对象玩arround了。您应该始终尝试使用私有或受保护对象。 希望这会对你有所帮助。

答案 2 :(得分:0)

这个答案可能无法解决您当前的问题(没有足够的代码来提出建议)但会帮助您朝着正确的方向前进。

为对象提供中央数据存储,您应该考虑使用单例设计模式。此外,由于数据将从多个线程访问,您应该使arraylist(在您的情况下)线程安全。

注意:如果使用同步列表,则应锁定对象以防止在迭代时访问。