java - 线程问题 : NullPointerException

标签 java android multithreading listview nullpointerexception

当我尝试将 listView 的最后一项中的文本设置为 MainActivity 中的 TextView 时遇到问题。它在“NullPointerException”运行时崩溃,因为我认为当我在 MainActivity 中调用它时,它没有完成在 ListView 上的下载,因此当 MainActivity 首次启动时,listView 没有完成他的工作和功能getCount()、getItem() 和我的函数 getLastElement() 仍然为空。 问题是我不太擅长处理线程(Wait(),notify(),..) 你能帮我解决这一切吗?

这是我的代码和 LogCat:

public class MainActivity extends Activity implements OnClickListener{

    private static Context mContext;

    public Button mExit, mHistory, mRating;

    public  TextView mSignal;

    HistoryAdapt myAdapter;

    HistoryItems m_myLastItem;

    ArrayList<HistoryItems> m_myListItem;

    Runnable m_run;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MainActivity.mContext=getApplicationContext();

        mExit=(Button)findViewById(R.id.ExitButton);
        mExit.setOnClickListener(this);

        mHistory=(Button)findViewById(R.id.HistoryButton);
        mHistory.setOnClickListener(this);

        mRating=(Button)findViewById(R.id.RateButton);
        mRating.setOnClickListener(this);

        mSignal=(TextView)findViewById(R.id.SignalOfTheDayTV);

        //### SET LAST ELEMENT INTO TEXTVIEW

        m_myListItem = new ArrayList<HistoryItems>(); 


        myAdapter= new HistoryAdapt(mContext, m_myListItem);

        new Thread(
                new Runnable(){
                    @Override
                    public void run(){

                            try{
                                ///Need to wait until the data to be downloaded inside HistoryAdapt so it can show the last element from the ListView here
                                HistoryParser parser = new HistoryParser();
                                parser.parse(getInputStream(HistoryAct.RSS_LINK));
                            } catch (XmlPullParserException e) {
                                Log.w(e.getMessage(), e);
                            } catch (IOException e) {
                                Log.w(e.getMessage(), e);
                            } finally {
                                //notify that the data finished to download 
                                MainActivity.this.runOnUiThread(
                                    new Runnable(){
                                        public void run(){

                                                m_myLastItem = myAdapter.getLastElement();
                                                //set last signal into TextView
                                                mSignal.setText(m_myLastItem.getTitle());



                                        }
                                    }
                                );
                            }

                    }
                }
            ).run();



//#RATER
       //   AppRater.app_launched(this);

        //  AppRater.showRateDialog(this, null);


        //Get a Tracker (should auto-report)
        ((AppManager) getApplication()).getTracker(AppManager.TrackerName.APP_TRACKER);
    }//oncreate

    private InputStream getInputStream(String link) {
        try {
            URL url = new URL(link);
            return url.openConnection().getInputStream();
        } catch (IOException e) {
            Log.w(Constants.DATA, "Exception while retrieving the input stream", e);
            return null;
        }
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public static Context getAppContext(){
        return MainActivity.mContext;
    }


    public void ExitState(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("You're about to quit Signals4Trading");
        builder.setIcon(R.drawable.five);
        //builder.setMessage("Your device has been registered successfully. You'll receive signals very soon.");
        builder.setMessage("Are you sure you want to quit?");
        builder.setCancelable(false);//can't click on the background of the activity
        builder.setPositiveButton("Yes",new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub

                Toast.makeText(getApplicationContext(),"See you soon", Toast.LENGTH_LONG).show();



                finish();


            }//OnClickListener PositiveButton
        });//anonymous class PositiveButton
        builder.setNegativeButton("No", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub

                Toast.makeText(getApplicationContext(),"Enjoy your visit", Toast.LENGTH_LONG).show();
            }

        });
        AlertDialog alertDialog  = builder.create();
        alertDialog.show();
    }//ExitState

    public void goToHistoryActivity(){
        Intent intent = new Intent(MainActivity.this, HistoryAct.class );
        startActivity(intent);
    }

    public void rateApp(){
        Intent intent = new Intent(MainActivity.this, Rate.class);
        startActivity(intent);
    }



    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()){
        case R.id.ExitButton:
            ExitState();
            break;          

        case R.id.HistoryButton:
            goToHistoryActivity();
            break;

        case R.id.RateButton:
            rateApp();
            break;

        }
    }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();

        //Get an Analytics tracker to report app starts & uncaught exceptions etc.
        GoogleAnalytics.getInstance(this).reportActivityStart(this);
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();

        //Stop the analytics tracking
        GoogleAnalytics.getInstance(this).reportActivityStop(this);
    }

}//MainActivity


package com.Signals4Trading.push.android;

import java.util.List;





import android.content.Context;
import android.content.Intent;
import android.os.StrictMode;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class HistoryAdapt extends BaseAdapter {


    private final List<HistoryItems>items;
    private final Context context;

    public HistoryAdapt(Context context,List<HistoryItems>items){
        this.context=context;
        this.items=items;

    }//constructor

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return items.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return items.get(position);
    }

    @Override
    public long getItemId(int id) {
        // TODO Auto-generated method stub
        return id;
    }


 //###FUNCTION THAT RETURN LAST ELEMENT


     public HistoryItems getLastElement(){
        return items.get(items.size()-1); 
    }




    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder holder;
        if (convertView == null) {
            convertView = View.inflate(context, R.layout.historyitems, null);
            holder = new ViewHolder();
            holder.itemTitle = (TextView) convertView.findViewById(R.id.itemTitleTV);
            holder.itemDate=(TextView) convertView.findViewById(R.id.itemDateTV);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }


         holder.itemTitle.setText(items.get(position).getTitle());
        holder.itemDate.setText(items.get(position).getDate());

        }

        return convertView;
    }

    class ViewHolder {
        TextView itemTitle;
        TextView itemDate;
    }


}
//HistoryAdapt

11-13 15:18:34.702: E/AndroidRuntime(7737): FATAL EXCEPTION: main
11-13 15:18:34.702: E/AndroidRuntime(7737): Process: com.Signals4Trading.push.android, PID: 7737
11-13 15:18:34.702: E/AndroidRuntime(7737): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.Signals4Trading.push.android/com.Signals4Trading.push.android.MainActivity}: 
java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1
11-13 15:18:34.702: E/AndroidRuntime(7737):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)

最佳答案

Activity 中的 onCreate() 调用正在调用:

m_myLastItem= HistoryAdapt.getLastElement();

但是,HistoryAdapt 的构造函数尚未被调用,这就是您在其中初始化静态字段items 的地方。我建议重新考虑这个类及其用法,因为您以实例方式使用它,但将其部分编码为静态类。遵循的一个好的经验法则是不要使静态方法依赖于正在构造的类。那时它只是一个实例方法。

关于java - 线程问题 : NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26885693/

相关文章:

android - 为具有不同 Unity 版本的 Android Studio 导出项目

android - 在Android中将PPT文件转换为图片

java - 如何对并发映射的值进行原子操作?

java - 调用者阻塞直到 getFoo() 准备好一个值?

java - HTTP:区别请求属性和 POST - 参数

java - Hibernate 条件、整数和 "like"

java - 使用 BitmapFactory 解码字节数组的原始大小位图

java - 如何使用 AsyncHttpClient 发送 JSON 正文?

java - Firebase 自定义事件参数未显示在 Firebase Analytics 控制台中

java - 多线程问题