0
votes

I use a thread and holder for downloading some data and then displaying a new view with buttons that allow you to browse further through the app. But i think i'm doing something wrong, because any next activity i use, crashes with a null pointer exception on the setContentView line. When i comment this line, nothing goes wrong (so i guess that means that the activity is declared good in the manifest and starts normally). It looks like because of the thread the new activity has no place to set the content to or something..

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

import com.hera.ontdekdelft.model.JJsonResponse;
import com.hera.ontdekdelft.listclasses.ListData;

import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class StartUp extends Activity
  {
    private static final String tag = StartUp.class.getName();
     public static final String SERIALIZEDDATA = "SerializedData";
     ProgressBar pbar;
     TextView tv1;
     Drawable background;
     Button btCategory, btMakeMyDay;
     RelativeLayout loadedBackground, loadingBackground;



    @Override
    public void onCreate(Bundle savedInstanceState)
      {
        super.onCreate(savedInstanceState);
        LoadData task = new LoadData();
        task.execute();


        String language =  Locale.getDefault().getISO3Language();
        background = getBackgroundImage();

            setContentView(R.layout.startup_loading);
            tv1=(TextView)findViewById(R.id.tvloading);
            if(language.equals("nld")){
                tv1.setText("bijwerken");
            }else{
                tv1.setText("loading");
            }
            pbar=(ProgressBar)findViewById(R.id.progressBar1);
            pbar.setVisibility(1);
            loadingBackground=(RelativeLayout)findViewById(R.id.startup_background_loading);
            loadingBackground.setBackgroundDrawable(background);



        }

    public Drawable getBackgroundImage(){
        Drawable d;
        Calendar c = Calendar.getInstance(); 
        int month = c.get(Calendar.MONTH);
        Log.i("month",String.valueOf(month));
        switch (month){
        default: d = getResources().getDrawable(R.drawable.homescreen_summer);break;
        case 0:d = getResources().getDrawable(R.drawable.homescreen_winter);break;
        case 1:d = getResources().getDrawable(R.drawable.homescreen_winter); break;
        case 2:d = getResources().getDrawable(R.drawable.homescreen_spring);break;
        case 3:d = getResources().getDrawable(R.drawable.homescreen_spring);break;
        case 4:d = getResources().getDrawable(R.drawable.homescreen_spring);break;
        case 5:d = getResources().getDrawable(R.drawable.homescreen_summer); break;
        case 6:d = getResources().getDrawable(R.drawable.homescreen_summer); break;
        case 7:d = getResources().getDrawable(R.drawable.homescreen_summer); break;
        case 8:d = getResources().getDrawable(R.drawable.homescreen_autumn); break;
        case 9:d = getResources().getDrawable(R.drawable.homescreen_autumn); break;
        case 10:d = getResources().getDrawable(R.drawable.homescreen_autumn); break;
        case 11:d = getResources().getDrawable(R.drawable.homescreen_winter); break;
        }
        return d;

    }

    private class LoadData extends AsyncTask<Void, Void, String> {

        @Override
        protected void onPreExecute() {

            super.onPreExecute();
        }

        protected void onPostExecute(String language) {
            super.onPostExecute(language);
            setContentView(R.layout.startup_loaded); 
            btCategory=(Button)findViewById(R.id.btn_category);
            loadedBackground=(RelativeLayout)findViewById(R.id.startup_background_loaded);
            loadedBackground.setBackgroundDrawable(background);
            if(language.equals("nld")){
                btCategory.setText("Ontdek Delft");
            }else{
                btCategory.setText("Discover Delft");
            }

              //newactivitybutton

            btCategory.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    startActivity(new Intent(StartUp.this, Overview.class));
                    finish();   
                }
            });

        }


        @Override
        protected String doInBackground(Void... params) {
            String language =  Locale.getDefault().getISO3Language();
             AssetManager assetManager = getAssets();
                InputStream inputStream = null;
                try {
                    inputStream = assetManager.open("originalDelftJson.json");
                } catch (IOException e) {
                    Log.e("tag", e.getMessage());
                }
                ObjectMapper objectMapper = new ObjectMapper();
                Log.i("tijdlog","start parsing" );
                try {

                     List<JJsonResponse> jsonResponse = objectMapper.readValue(inputStream, new TypeReference<List<JJsonResponse>>() { });
                        Log.i("tijdlog","einde parsing" );
                        // 
                          final  List<JJsonResponse> myGlobalVariable = jsonResponse;

                          ((ApplicationController)getApplication()).setGlobalData(myGlobalVariable);



                          List<ListData> ld = new ArrayList<ListData>();
                         int selectedPic;
                         JJsonResponse e;
                         int k =0;
                         for(int i=0;i < jsonResponse.size() ;i++){
                             e = jsonResponse.get(i);
                             for(int j=0; j<e.venue.themes.size();j++){
                                 if (e.venue.themes.get(j).mobile == true){
                                     selectedPic = 0;
                                     String tip;
                                     String theme;
                                     if (language.equalsIgnoreCase("nld")){
                                         tip=e.venue.tip; 
                                         theme=e.venue.themes.get(j).name;
                                     }else{
                                         tip=e.venue.tip_en;
                                         theme=e.venue.themes.get(j).name_en;
                                     }
                                     // pic selected pic
                                     String photoUrl = null;
                                     if (e.venue.venue_photos.isEmpty() == false){
                                        for(int l=0; l < e.venue.venue_photos.size() ;l++){
                                             if(e.venue.venue_photos.get(l).selected == true){ 
                                                 selectedPic = l;
                                             }
                                             photoUrl=e.venue.venue_photos.get(selectedPic).medium;
                                         }
                                     }else
                                         {
                                         photoUrl=null; // null no pic--> add link later
                                       }
                                     ld.add(new ListData(e.venue.id, e.venue.name, photoUrl, tip, theme));//nieuwe maken
                                     k++;
                                 }  
                             } 
                         }

                         Collections.sort(ld, ListData.ListDataThemeAndNameComparator); // vergelijken op thema
                         for(int z=0;z < ld.size() ;z++){
                             Log.i("ld nr " + String.valueOf(z), ld.get(z).name + " theme: " + ld.get(z).theme + " & venue id= "+ ld.get(z).venueID);
                         }

                // save
                         ((ApplicationController)getApplication()).setListData(ld);  



                } catch (JsonParseException e) {
                    // XXX Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // XXX Auto-generated catch block
                    e.printStackTrace();
                }
            return language;
        }

    }

}

the new activity where my error occurs:

import android.app.Activity; import android.os.Bundle;

public class Overview extends Activity{

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

}

xml splash;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@drawable/splash"
    >


</LinearLayout>

edit: i edited my code. now using a AsyncTask, it seemed to be the solution like LuxuryMode suggested below, but it doesn't work either. Still same nullpointerexception when setContentView... error log:

07-24 19:53:50.411: E/AndroidRuntime(29618): FATAL EXCEPTION: main
07-24 19:53:50.411: E/AndroidRuntime(29618): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hera.ontdekdelft/com.hera.ontdekdelft.Overview}: java.lang.NullPointerException
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2787)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2803)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.ActivityThread.access$2300(ActivityThread.java:135)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.os.Handler.dispatchMessage(Handler.java:99)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.os.Looper.loop(Looper.java:144)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.ActivityThread.main(ActivityThread.java:4937)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at java.lang.reflect.Method.invokeNative(Native Method)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at java.lang.reflect.Method.invoke(Method.java:521)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at dalvik.system.NativeStart.main(Native Method)
07-24 19:53:50.411: E/AndroidRuntime(29618): Caused by: java.lang.NullPointerException
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.view.ViewGroup.addViewInner(ViewGroup.java:1977)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.view.ViewGroup.addView(ViewGroup.java:1873)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.view.ViewGroup.addView(ViewGroup.java:1853)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:226)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:216)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.Activity.setContentView(Activity.java:1665)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at com.hera.ontdekdelft.Overview.onCreate(Overview.java:12)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1069)
07-24 19:53:50.411: E/AndroidRuntime(29618):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2751)
07-24 19:53:50.411: E/AndroidRuntime(29618):    ... 11 more
2
Can you post the stacktrace please? - LuxuryMode

2 Answers

1
votes

There are two rules in the Android threading model: 1) dont block the main (UI) thread 2) dont manipulate the UI from off of the main (UI) thread. You seem to be having an issue with the second of those rules. You can try using Activity#runOnUiThread(Runnable) instead of using that handler, but in general what you're doing is really messy and generally a terrible idea :) Also, unless I'm missing something up, how exactly is your handler even usable inside of your startup thread if you're initializing it after you start the thread? You seem to be relying on the thread scheduling going a certain way which is just a bad idea as well.

In all likelihood, what you need to use is an AsyncTask. Set your contentview immediately in onCreate and then execute your AsyncTask which downloads your data. Then in onPostExecute of your task, do whatever relevant UI changes are necessary.

UPDATE -

in onPostExecute, call the super right away. Also, don't start your Activity by calling startActivity(new Intent ("com.hera.ontdekdelft.OVERVIEW"));, instead it should be startActivity(new Intent(Startup.this, Overview.class));

Also, from the looks of the stacktrace, the crash is occurring when you try starting the new Activity. So I would look there on line 12 to see what the problem is.

UPDATE -

As I pointed out in our discussion below:

You cannot set the contentView of your Activity to findViewById(whatever). findViewById looks through the current contentView and tries to find a view that matches the id you passed in. But you havent set any contentview yet so theres nothing to find. Therefore you crash with a nullpointer when you try setting the contentview to the null view returned by your call to findViewById! You need to set the view to whatever the view is for that Activity. setContentView(R.layout.overview_layout) or setContentView(new OverviewView(this))

0
votes

setContentView(..) is a method of Activity. You can not call it in your Runnable, it's out of scope. Result is a nullpointer.

Your approach of setting the contentView inside a Runnable is rather weird.. Maybe alter your design a bit? Maybe you can create more than one Activity rather than switching layouts of 1 Activity..