无法分配最终的局部变量,因为它是在封闭类型java中定义的

时间:2014-11-26 10:05:59

标签: java android multithreading list

我创建了类childList,它实现了一个接口`GetChildList``,如下所示:

    package com.example.hakslogin;

import java.util.ArrayList;
import java.util.List;
import com.example.hakslogin.GetChildList;
import com.example.hakslogin.HandleJSON;

public class childList implements GetChildList
{
    private HandleJSON obj;
    public String urlString = "http://192.168.x.xx:xxxx/getdb";
    public void callFetchJSONChild(){
        HandleJSON obj = new HandleJSON(urlString);
        List<String> list = obj.fetchJSONChild(this);
   }
    @Override
    public void onGetChildList(List<String> list) {
        // here your work with list
        //List<String> child = new ArrayList<String>();
        obj = new HandleJSON(urlString);
        list = obj.fetchJSONChild(this);
    }
}

我有一个方法fetchJSONChild(),如下所示:

List<String> child = new ArrayList<String>();
           public void fetchJSONChild(final GetChildList callBack){
                final String[] str =  new String[3];
               // final List<String> child = new ArrayList<String>();
            Thread thread = new Thread(new Runnable(){
               @Override
               public void run() {
               try {
                  URL url = new URL("http://192.168.x.xx:xxxx/childform_list/0.0.0.0/8069/new_db/admin/123456");
                  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                  conn.setReadTimeout(30000 /* milliseconds */);
                  conn.setConnectTimeout(50000 /* milliseconds */);
                  conn.setRequestMethod("GET");
                  conn.setRequestProperty("User-Agent", "GYUserAgentAndroid");
                  conn.setRequestProperty("Content-Type", "application/json");
                  conn.setDoInput(true);
                  conn.setUseCaches (false);
                  // Starts the query
                  if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13)
                  {
                   conn.setRequestProperty("Connection", "close"); 
                  }
                  conn.connect();

                  System.out.println("Before url.openStream()");
               InputStream stream = conn.getInputStream();//.openStream();
               System.out.println("After url.openStream()");
            String data = convertStreamToString(stream);
            // for example String data = "1,2,3";
            child.addAll(Arrays.asList(data.split(",")));

            readAndParseJSON(data);
            stream.close();
            callBack.onGetChildList(child);
               } catch (Exception e) {
                  e.printStackTrace();
               }
               }

             thread.start();

         }

在这个方法中,线程正在运行,我希望将我放入list<string>的拆分字符串数据放入我的活动中,下面是我调用ChildActivity的活动:

package com.example.hakslogin;

import java.util.ArrayList;
import java.util.List;

import android.support.v7.app.ActionBarActivity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.hakslogin.GetChildList;

public class ChildActivity extends ActionBarActivity {

    private ListView lv_child;
    List<String> child = new ArrayList<String>();
    Button btn_home;
    Button btn_add;
    private HandleJSON obj;
    public String urlString = "http://192.168.x.xx:xxxx/getdb";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_child);


        obj = new HandleJSON(urlString);
        obj.fetchJSONChild(null);
        lv_child = (ListView)findViewById(R.id.lv_child); 
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, child);
        lv_child.setAdapter(adapter);
}

public void onGetChildList(List<String> list) {
   //this method will be called after thread in fetchJSONChild ended
   child = list;
   lv_child = (ListView)findViewById(R.id.lv_child); 
   String arr[]=child.toArray(new String[list.size()]);
   String[] Temp= new String[2];
          Temp[0] = arr[2].toString();
          array.add(Temp[0].split(":")[1]);
          String s = Temp[0].toString();
   ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,array);
   lv_child.setAdapter(adapter);

}

}

当我在android.view.viewrootimpl$calledfromwrongthreadexception的{​​{1}}方法中填充listview list时,我收到例外onGetChildList

请建议我,我应该等待回复。

由于

4 个答案:

答案 0 :(得分:0)

final List<String> child = new ArrayList<String>();

并替换

child = new ArrayList<String>(Arrays.asList(data1.split(",")));

child.addAll(Arrays.asList(data1.split(","))

答案 1 :(得分:0)

1)final意味着你永远不会改变这个变量。所以你应该使用全局变量或者使用空数组初始化它然后填充它。无论如何,你有奇怪的算法...

2)你启动Thread。所以其中的所有代码都是异步的。您的操作return child;(在您的情况下)始终返回null。

所以,我建议你为你的线程使用回调导致它的同步操作......

好的,那就是它的外观:

1)声明接口:

public interface GetChildList{
        public void onGetChildList(List<String> list);
}

2)在你的班级(你呼叫fetchJSONChild()的地方)实施它:

import com.example.hakslogin.GetChildList;

public class ChildActivity extends ActionBarActivity implements GetChildList {

    Button btn_home;
    Button btn_add;
    private HandleJSON obj;
    public String urlString = "http://192.168.x.xx:xxxx/getdb";

    List<String> child = new ArrayList<String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_child);


        obj = new HandleJSON(urlString);
        obj.fetchJSONChild(null);
        lv_child = (ListView)findViewById(R.id.lv_child); 
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, child);
        lv_child.setAdapter(adapter);
    }
    Handler mHandler = new Handler() {
      public void handleMessage(android.os.Message msg) {
        lv_child = (ListView)findViewById(R.id.lv_child); 
         String arr[]=child.toArray(new String[list.size()]);
         String[] Temp= new String[2];
         Temp[0] = arr[2].toString();
         array.add(Temp[0].split(":")[1]);
         String s = Temp[0].toString();
         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,array);
         lv_child.setAdapter(adapter);
      };
   };



    @Override
    public void onGetChildList(List<String> list) {
       //this method will be called after thread in fetchJSONChild ended
       child = list;
       mHandler.sendEmptyMessage(0);

    }
}

3)你的fetchJSONChild会是这样的:

public void fetchJSONChild(final GetChildList callBack){

        final List<String> child = new ArrayList<String>();
        Thread thread = new Thread(new Runnable(){

            @Override
            public void run() {

                try {

                    URL url = new URL("http://192.168.x.xx:xxxx/childform_list/0.0.0.0/8069/new_db/admin/123456");
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setReadTimeout(30000 /* milliseconds */);
                    conn.setConnectTimeout(50000 /* milliseconds */);
                    conn.setRequestMethod("GET");
                    //conn.setRequestProperty("User-Agent", "GYUserAgentAndroid");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.setDoInput(true);
                    //conn.setUseCaches (false);
                    // Starts the query
                    if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {

                        conn.setRequestProperty("Connection", "close"); 
                    }
                    conn.connect();

                    System.out.println("Before url.openStream()");
                    InputStream stream = conn.getInputStream();//.openStream();
                    System.out.println("After url.openStream()");
                    String data = convertStreamToString(stream);
                    // for examole data = "1,2,3";

                    child.addAll(Arrays.asList(data.split(","));
                    readAndParseJSON(data);
                    stream.close();

                    callBack.onGetChildList(child);
                } catch (Exception e) {

                    e.printStackTrace();
                }
            }
        });
        thread.start(); 
    }

4)在您的班级中,您实施了GetChildList来电fetchJSONChild(this)

5)线程结束后,它会调用onGetChildList来处理数据。

答案 2 :(得分:0)

这种花费时间并在后台线程中工作而不冻结屏幕的过程无法返回处理值。因为,方法将在线程开始之前完成执行!!你启动线程。当在runOnUiThread中准备好结果时,你可以做任何你想做的事。比如停止加载图标并向用户显示数据。那个概念。

List<String> child;
public void fetchJSONChild(){
         //= new ArrayList<String>();
    Thread thread = new Thread(new Runnable(){
       @Override
       public void run() {
       try {
          URL url = new URL("http://192.168.x.xx:xxxx/childform_list/0.0.0.0/8069/new_db/admin/123456");
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setReadTimeout(30000 /* milliseconds */);
          conn.setConnectTimeout(50000 /* milliseconds */);
          conn.setRequestMethod("GET");
          //conn.setRequestProperty("User-Agent", "GYUserAgentAndroid");
          conn.setRequestProperty("Content-Type", "application/json");
          conn.setDoInput(true);
          //conn.setUseCaches (false);
          // Starts the query
          if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13)
          {
           conn.setRequestProperty("Connection", "close"); 
          }
          conn.connect();

          System.out.println("Before url.openStream()");
       InputStream stream = conn.getInputStream();//.openStream();
       System.out.println("After url.openStream()");
    String data = convertStreamToString(stream);
    // for examole data = "1,2,3";

    child = new ArrayList<String>(Arrays.asList(data.split(","))); // <<<<---- data not data1!?
    readAndParseJSON(data);

    runOnUiThread(new Runnable() {
                public void run() {
                    // here you can update the ui with the child values.
                    for (int i=0;i<child.size();i++)
                         Log.e("Child", child.get(i));
                }
            });
       stream.close();

       } catch (Exception e) {
          e.printStackTrace();
       }
       }
    });

     thread.start();
 }

注意:如果activity类中的方法,此解决方案可以正常工作。如果没有,请说出来我可以提供适当的解决方案。

答案 3 :(得分:-1)

删除子final声明并将其设为全局变量。