尝试从线程刷新我的视图,但它给我一个错误

时间:2016-10-07 10:52:32

标签: android multithreading

这是我的问题:我试图在线程中添加一个元素,但它不起作用。 这是我的活动代码:

public class AireDeJeu extends AppCompatActivity {
private final static int mObjectif = 100;
private int mProgression = 0;

private ImageView trou1, trou2, trou3, trou4, trou5, trou6, trou7, trou8, trou9, trou10, trou11, trou12;

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


     trou1 = (ImageView)findViewById(R.id.trou1); trou2= (ImageView)findViewById(R.id.trou2); trou3 = (ImageView)findViewById(R.id.trou3);
     trou4 = (ImageView)findViewById(R.id.trou4); trou5 = (ImageView)findViewById(R.id.trou5); trou6 = (ImageView)findViewById(R.id.trou6);
     trou7 = (ImageView)findViewById(R.id.trou7); trou8 = (ImageView)findViewById(R.id.trou8); trou9 = (ImageView)findViewById(R.id.trou9);
     trou10 = (ImageView)findViewById(R.id.trou10); trou11 = (ImageView)findViewById(R.id.trou11); trou12 = (ImageView)findViewById(R.id.trou12);

    trou1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
        }
    });
/*
 *
 * I clear my 11 other onClickListener to be more clear.
 *
 */

        GenerateurPartie generateurPartie = new GenerateurPartie(niveau);

}

public void setPersonnage(int pId, int pRes){
    ImageView perso = (ImageView)findViewById(pId);
    perso.setImageResource(pRes);
}

}

它叫我的下一堂课:" GenerateurPartie"在哪里开始我的线程:

public class GenerateurPartie extends GenerateurPerso{

private int mNiveau;
public static int mAvancement = 0;
private int mDelai;
private Thread mThread;
private Perso mPerso;

private final HandlerDelai handlerDelai = new HandlerDelai();

protected static PlacementPerso mPlacementPerso = new PlacementPerso();

public GenerateurPartie(int pNiveau) {
    this.mNiveau = pNiveau;
    this.mDelai = 2500;

    mPlacementPerso.PlacementPerso();
   mThread = new Thread(new Runnable() {
       @Override
       public void run() {
           try {
           int i = 0;
               while (mAvancement < 100) {

                   i += 1;

                   if (mAvancement >= 80)
                       mDelai = mDelai / 2;

                       Thread.sleep(mDelai);

                   handlerDelai.postDelayed(new Runnable() {
                       @Override
                       public void run() {
                           mPerso = GenerateurPerso(mNiveau, mAvancement);

                           mPlacementPerso.aPlacer(mPerso);
                       }
                   }, mDelai);
               }
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
   }});
    mThread.start();

    }
}

我没有向你展示我的班级&#34; GenerateurPerso&#34;澄清我的信息,因为它很有效。下一个是我的班级&#34; PlacementPerso&#34;,logcat错误从它变成了。它延伸到我的活动&#34; AireDeJeu&#34; :

public class PlacementPerso extends AireDeJeu{
private boolean trou1, trou2, trou3, trou4, trou5, trou6, trou7, trou8, trou9, trou10, trou11, trou12;

private Random r = new Random();
private int random, baseMax, baseMin;

public void PlacementPerso(){
    trou1 = true; trou2 = true; trou3 = true; trou4 = true; trou5 = true; trou6 = true; trou7 = true; trou8 = true; trou9 = true; trou10 = true; trou11 = true; trou12 = true;
    random = 1; baseMax = 12; baseMin = 1;
}

public void aPlacer(Perso pPerso){
    final int ressource = pPerso.getRessource();
    // ressource will be like : "R.drawable.img"

    random = r.nextInt((baseMax - baseMin) + 1) + baseMin;
    int trouId = 0;

    switch(random){
        case 1:
            if(trou1){
                trouId = R.id.trou1;
                trou1=false;
            }
            else {
                aPlacer(pPerso);
            }
            break;
        /**
         *
         * To clarify the code again I leave the 11 other case, they do the same thing, just the trouId value change.
         *
         */
    }

    final int pId = trouId;

    //This is my problem, it come from here
 super.setPersonnage(pId,ressource);
}

我已经尝试了很多解决方案,我将super.setPersonnage(pId,ressource);替换为:

runOnUiThread(new Runnable() {
        @Override
        public void run() {
           Log.d("Perso","Entrer dans runOnUiThread");
            ImageView perso = (ImageView)findViewById(pId);
            if(perso == null)
                Log.d("Perso","L'imageVew pour placer l'image est null !!!!!");
            else
                Log.d("Perso","L'imageVew pour placer l'image n'est pas null");
            perso.setImageResource(ressource);
        }

    });

但没有什么比这更好的了。我试图在findViewById之前添加setContentView(R.layout.aire_de_jeu),但它没有改变任何东西。 (其他的事情:当我尝试这个代码时,第一个Log出现但第二个或第三个出现......)

要完成,这是我的logcat:

10-07 11:30:47.758 31782-31782/com.dunomade.ecraseurdetaupe E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.dunomade.ecraseurdetaupe, PID: 31782
                                                                          java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
                                                                              at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:72)
                                                                              at android.support.v7.app.AppCompatDelegateImplV7.<init>(AppCompatDelegateImplV7.java:146)
                                                                              at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java:28)
                                                                              at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:41)
                                                                              at android.support.v7.app.AppCompatDelegateImplV23.<init>(AppCompatDelegateImplV23.java:29)
                                                                              at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:191)
                                                                              at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:173)
                                                                              at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:511)
                                                                              at android.support.v7.app.AppCompatActivity.findViewById(AppCompatActivity.java:183)
                                                                              at com.dunomade.ecraseurdetaupe.AireDeJeu.setPersonnage(AireDeJeu.java:136)
                                                                              at com.dunomade.ecraseurdetaupe.PlacementPerso.aPlacer(PlacementPerso.java:175)
                                                                              at com.dunomade.ecraseurdetaupe.GenerateurPartie$1$1.run(GenerateurPartie.java:56)
                                                                              at android.os.Handler.handleCallback(Handler.java:815)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                              at android.os.Looper.loop(Looper.java:207)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5728)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

它告诉错误来自行:136,他来了:

 public void setPersonnage(int pId, int pRes){
    ImageView perso = (ImageView)findViewById(pId); //Line 136
    perso.setImageResource(pRes);
}

我试着看看问题是否来自我的论点,所以我做了:

 public void setPersonnage(int pId, int pRes){
    ImageView perso = (ImageView)findViewById(R.id.trou1);
    perso.setImageResource(R.drawable.img);
}

但问题保持不变。

也许是因为我试图改变线程中的视图?!

我真的希望有人可以帮我解决这个问题。 Maye我的问题是我的班级&#34; PlacementPerso&#34;不能在我的线程中工作,但我认为它适用于它。

感谢&#39; s advance =)

1 个答案:

答案 0 :(得分:0)

为了更清楚,我会试着告诉你发生了什么:

我尝试了很多可能性,但没有任何作用。但它帮助我找到真正的问题所在。所以我留下一些代码以便更清楚。我希望它能帮助你找到解决问题的方法。

所以这是我的活动:

public class AireDeJeu extends AppCompatActivity {

//I create all my ImageViews outside onCreate
public ImageView trou1, trou2, trou3, trou4, trou5, trou6, trou7, trou8, trou9, trou10, trou11, trou12;

//I make onCreate public to try to get the views later.
@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aire_de_jeu);

     //I get the view for all ImageView

     trou1 = (ImageView)findViewById(R.id.trou1); trou2= (ImageView)findViewById(R.id.trou2); trou3 = (ImageView)findViewById(R.id.trou3);
     trou4 = (ImageView)findViewById(R.id.trou4); trou5 = (ImageView)findViewById(R.id.trou5); trou6 = (ImageView)findViewById(R.id.trou6);
     trou7 = (ImageView)findViewById(R.id.trou7); trou8 = (ImageView)findViewById(R.id.trou8); trou9 = (ImageView)findViewById(R.id.trou9);
     trou10 = (ImageView)findViewById(R.id.trou10); trou11 = (ImageView)findViewById(R.id.trou11); trou12 = (ImageView)findViewById(R.id.trou12);
}
}

这里一切都很好,没有任何错误。我可以设置像trou6.setImageRessource(R.id.img);这样的资源,它可以正常工作。

在此之后,我调用一个新线程。它包含一个随机选择ImageView和另一个随机选择ressource,它工作的每一个Xs(这就是为什么我使用Thread,使用thread.sleep();,来制作一段时间)和它为我的处理程序创建一条消息:

final private PlacementHandler placementHandler = new PlacementHandler();
final int KEY_PLACEMENT_PERSO = 1;

//ressource is like "R.drawable.img1", msg.arg2 is 0 because I don't need it, and viewTrou is the ImageView selected by the random (like trou1, or trou2...)
Message msg = placementHandler.obtainMessage(KEY_PLACEMENT_PERSO,ressource,0,viewTrou);
    placementHandler.sendMessage(msg);

要完成,这就是问题所在,在我的handleMessage

public class PlacementHandler extends Handler {
    @Override
    public void handleMessage(Message msg){
        super.handleMessage(msg);

        //here is the problem, I get a NullPointerException
        ImageView perso = (ImageView)msg.obj;
        perso.setImageResource(msg.arg1);
    }
}

要确保问题不是来自我的msg.obj或我的msg.arg1

public class PlacementHandler extends Handler {
    @Override
    public void handleMessage(Message msg){
        super.handleMessage(msg);

        //here is the problem again, my NullPointerException stop my app one more time
        trou1.setImageResource(R.drawable.img1);
    }
}

这是我不明白的地方:我在ImageViews之外创建了onCreate公开,因此我可以在我的Handler中访问它们,但它们没有视图(因为视图在onCreate中创建。如何让我的ImageView获取内部视图?

也许解决方法是在获得新的findViewById之前对布局进行膨胀,我也尝试过这种方式,但我不知道该怎么做......

我希望我很清楚,你明白我的问题是什么。 对不起我的英语不好。 非常感谢帮助。

PS:我已经尝试清除该项目,但没有任何事情发生。