1

我在构建设计良好的面向对象系统方面没有太多经验,这次我即兴创作,这导致系统无法工作并且没有给我任何错误。

基本上在我的 android 应用程序中,我有一个用户配置文件活动,它调用一个使用用户 ID 查询远程数据库的类,并返回用户头像和用户名的值。

直到该类嵌套在配置文件活动类中之前它还不错,但是我决定将其移出那里并更改一些其他内容,现在当我转到我的个人资料时,我看不到我的头像,也看不到我的用户名.

这是 GetUserData 类:

public class GetUserData extends Activity {
    private String currentlyLoggedInUserString;
    SharedPreferences sharedPrefs;
    Editor editor;
    int currentlyLoggedInUser;
    private JSONParser jsonParser = new JSONParser();
    private Configurationz configurationz = new Configurationz();
    private ToastMaker toastMaker = new ToastMaker();
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_USER_AVATAR = "user_avatar";
    private static final String TAG_USER_NAME = "user_name";
    private static final String TAG_USER_EMAIL = "user_email";
    private static final String TAG_USER_SEX = "user_sex";
    private static final String TAG_USER_DATE_REGISTERED = "user_date_registered";
    private static final String TAG_USER_LAST_SEEN = "user_last_seen";
    private static final String TAG_USER_PASSWORD = "user_password";
    private static final String APP_SHARED_PREFS = "asdasd_preferences";
    private String userName;
    private String userEmail;
    private String userSex;
    private String userPassword;
    private String userAvatar;
    private String userDateRegistered;
    private String userLastSeen;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserEmail() {
        return userEmail;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public String getUserAvatar() {
        return userAvatar;
    }

    public void setUserAvatar(String userAvatar) {
        this.userAvatar = userAvatar;
    }

    public String getUserDateRegistered() {
        return userDateRegistered;
    }

    public void setUserDateRegistered(String userDateRegistered) {
        this.userDateRegistered = userDateRegistered;
    }

    public String getUserLastSeen() {
        return userLastSeen;
    }

    public void setUserLastSeen(String userLastSeen) {
        this.userLastSeen = userLastSeen;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sharedPrefs = getApplicationContext().getSharedPreferences(APP_SHARED_PREFS, Context.MODE_PRIVATE);
        new GetUserDataGetter().execute();
    }

    public class GetUserDataGetter extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... params) {
            int success;
            try {

                List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                // fix these shitty variables.
                currentlyLoggedInUser = sharedPrefs.getInt("currentLoggedInUserId", 0);
                currentlyLoggedInUserString = Integer.toString(currentlyLoggedInUser);
                parameters.add(new BasicNameValuePair("user_id", currentlyLoggedInUserString));

                final JSONObject json = jsonParser.makeHttpRequest(configurationz.URL_PHP_GET_USER_DATA, "POST", parameters); 
                success = json.getInt(TAG_SUCCESS);
                if (success == 1) {
                    // user data found
                    setUserLastSeen(json.getString(TAG_USER_LAST_SEEN));
                    setUserDateRegistered(json.getString(TAG_USER_DATE_REGISTERED));
                    setUserAvatar(json.getString(TAG_USER_AVATAR));
                    setUserSex(json.getString(TAG_USER_SEX));
                    setUserPassword(json.getString(TAG_USER_PASSWORD));
                    setUserEmail(json.getString(TAG_USER_EMAIL));
                    setUserName(json.getString(TAG_USER_NAME));

                    //return json.getString(TAG_USER_AVATAR);
                    return null;
                } else if (success == 2) {
                    //toast about not being able to connect to db;
                    runOnUiThread(new Runnable() {
                        public void run() {

                            //this might cause some SHIT!!!!!!!!!!!! TEST IT!!!
                            toastMaker.toast(getBaseContext(), configurationz.ERROR_MESSAGES_SIGNUP_DEVICE_UNABLE_TO_TAKE_PHOTOS, configurationz, Toast.LENGTH_LONG);

                        }
                        });


                    setUserLastSeen("");
                    setUserDateRegistered("");
                    setUserAvatar("");
                    setUserSex("");
                    setUserPassword("");
                    setUserEmail("");
                    setUserName("");
                    return null;
                } else {

                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }

    }
}

这是 MyProfile 类:

public class MyProfile extends ActionBarAndSlidingMenu {
    private TableRow myProfileActionButtonsHolder;
    private TextView tvUserName;
    private ImageButton iUserAvatar;
    private Bitmap iUserAvatarBitmap;
    private String avatarPath;
    private String userName;
    private static final String APP_SHARED_PREFS = "asdasd_preferences";
    SharedPreferences sharedPrefs;
    Editor editor;
    int currentlyLoggedInUser;
    boolean userLoggedInState = false;
    private GetUserData getUserData = new GetUserData();

    public MyProfile() {
        super(R.string.app_name);
    }

    // do a check here whether this is the user themselves or some other user

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sharedPrefs = getApplicationContext().getSharedPreferences(APP_SHARED_PREFS, Context.MODE_PRIVATE);
        setContentView(R.layout.user_profile);

        // check whether user is logged in, otherwise redirect them to
        // login/signup page
        userLoggedInState = sharedPrefs.getBoolean("userLoggedInState", false);
        if (!userLoggedInState) {
            // start intent to get them out of here.
            // Research whether this step is necessary at all
        }

        // define the view components
        myProfileActionButtonsHolder = (TableRow) findViewById(R.id.userProfileActionButtonsHolder);

        // set avatar image
        iUserAvatar = (ImageButton) findViewById(R.id.iUserAvatar);
        avatarPath = getUserData.getUserAvatar();
        if (avatarPath != "") {
            iUserAvatarBitmap = BitmapFactory.decodeFile(avatarPath);
            iUserAvatar.setImageBitmap(iUserAvatarBitmap);
        } else {
            iUserAvatar.setImageResource(R.drawable.avatar_default_male);
        }

        //set user display name
        userName = getUserData.getUserName();
        tvUserName = (TextView) findViewById(R.id.tvUserName);
        tvUserName.setText(userName);


        // create action buttons fragment with "edit" and "settings" buttons
        getSupportFragmentManager().beginTransaction().replace(R.id.userProfileActionButtonsHolder, new MyProfileActionButtonsFragment()).commit();

    }
}
4

2 回答 2

3

首先,您需要阅读一般的编程知识,特别是正确的编码指南,因为这有点混乱。一旦您的项目变得更加复杂,这将变得不可读和不可调试。其次,您应该阅读 Android 的工作原理。

简而言之,这是您的问题:

Activity 不仅仅是 Android 自己的类版本,您不能这样使用它。Activity 表示向用户显示的屏幕。没有屏幕可以显示?没有活动。因此,您的 getUserData 活动应该是一个常规类,而不是扩展活动。

现在,在 MyProfile 中,您只需声明一个成员变量

private GetUserData getUserData = new GetUserData();

这没有任何作用,它肯定永远不会运行该类的 onCreate。因此,您的任务永远不会执行,并且您的所有字段都返回 null。

简而言之,以下是要做的事情:

  1. 创建一个 UserDetails 类,该类具有一个构造函数,该构造函数采用用户名等以及获取这些详细信息所需的 getter。什么都不加。这就是我们所说的 Java 版本的值对象。

    public class UserDetails {
        private final String mUsername;
    
        public UserDetails(String username) {
             mUsername = username;
        }
    
        public String getUsername() {
            return mUsername;
        }
    }
    
  2. 使用 onUserDetailsReceived(UserDetails userDetails) 方法创建一个名为 IOnUserDetailsReceivedListener 的接口。这样做的原因是您的下载任务需要一些时间。您需要在完成后得到通知,这就是我们使用此界面的目的。这称为侦听器模式。

    public interface IOnUserDetailsReceivedListener {
        public void onUserDetailsReceived(UserDetails userDetails);
        public void onUserDetailsError();
    }
    
  3. 创建一个包含您的 AsyncTask 并具有方法 retrieveUserDetails(); 的类 Downloader;或者其他的东西。在该方法中,运行异步任务进行下载。当您从服务器获取数据时,将其填充到新的 UserDetails(...) 对象中,然后调用 listener.onUserDetailsReceived(userDetails)。

    public class UserDetailsDownloader {
        private IOnUserDetailsReceivedListener mListener;
    
        public UserDetailsDownloader(IOnUserDetailsReceivedListener listener) {
            mListener = listener;
        }
    
        public void downloadUserDetails() {
            //Execute the async task here. In it's onPostExecute, do       mListener.onUserDetailsReceived(userDetails).
        }
    
        private class DownloaderTask extends AsyncTask<String, Integer, UserDetails> {
            @Override
            protected UserDetails doInBackground(String... params) {
                //Download code
                //In downloading there might go stuff wrong. If so, return null as an easy method without any error handling.
                UserDetails userDetails = new UserDetails("downloadedUsername");
                return userDetails;
            }
    
    
            @Override
            protected void onPostExecute(UserDetails userDetails) {
                if(userDetails == null) {
                    if(mListener != null) {
                        //Something went wrong. Tell the listener.
                        mListener.onUserDetailsError();
                    }               
                } else {
                    if(mListener != null) {
                        //Cool! Lets pass the userDetails to the activity.
                        mListener.onUserDetailsReceiver(userDetails);
                    }
                }
            }   
        }
    }
    
  4. 让您的活动实现 IOnUserDetailsReceivedListener。

    public void UserActivity extends Activity implements IOnUserDetailsReceivedListener {
        private UserDetailsDownloader mUserDetailsDownloader;
    
        public void onCreate(...) {
            mUserDetailsDownloader = new UserDetailsDownloader(this);
            mUserDetailsDownloader.downloadUserDetails();
        }
    
        public void onUserDetailsReceived(UserDetails userDetails) {
            //Yeeh we received user data.
        }
    
        public void onUserDetailsError() {
            //Something went wrong. Tell the user?
        }
    }
    
  5. 当您的任务完成后,它会调用您的活动 onUserDetailsReceived 方法并将 UserDetails 值对象传递给您,然后您可以使用它做您想做的事情。

于 2013-11-01T13:56:08.663 回答
2

我不知道这是否是您唯一的问题,但评论太多了。你不应该runOnUiThread()使用doInBackground()

 runOnUiThread(new Runnable() {
     public void run() {

     //this might cause some SHIT!!!!!!!!!!!! TEST IT!!!
     toastMaker.toast(getBaseContext(), configurationz.ERROR_MESSAGES_SIGNUP_DEVICE_UNABLE_TO_TAKE_PHOTOS, configurationz, Toast.LENGTH_LONG);

    }
});

这就是为什么AsyncTaskhasonPostExecute()和它的其他方法......它们都运行在UI Thread除了doInBackground()

而不是return nullreturn成功and depending on that value, do what you need to inonPostExecute()`。

编辑

onPostExecute()从声明doInBackground()中的第三个返回的内容中获取其参数。所以你可以改变它或返回一个to from 。parampublic class GetUserDataGetter extends AsyncTask<String, String, String>paramStringonPostExecute()doInBackground()

AsyncTask 文档

于 2013-11-01T13:46:12.553 回答